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 2008 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_descr_tree(dev_info_t *, usba_device_t *, 116 usb_client_dev_data_t *); 117 static void usba_process_cfg_descr(usba_reg_state_t *); 118 static int usba_process_if_descr(usba_reg_state_t *, boolean_t *); 119 static int usba_process_ep_descr(usba_reg_state_t *); 120 static int usba_process_cv_descr(usba_reg_state_t *); 121 static int usba_set_parse_values(dev_info_t *dip, usba_device_t *usba_device, 122 usba_reg_state_t *state); 123 static void* usba_kmem_realloc(void *, int, int); 124 static void usba_augment_array(void **, uint_t, uint_t); 125 static void usba_make_alts_sparse(usb_alt_if_data_t **, uint_t *); 126 127 static void usba_order_tree(usba_reg_state_t *); 128 129 static void usba_free_if_array(usb_if_data_t *, uint_t); 130 static void usba_free_ep_array(usb_ep_data_t *, uint_t); 131 static void usba_free_cv_array(usb_cvs_data_t *, uint_t); 132 133 static int usba_dump_descr_tree(dev_info_t *, usb_client_dev_data_t *, 134 usb_log_handle_t, uint_t, uint_t); 135 static void usba_dump_if(usb_if_data_t *, usb_log_handle_t, 136 uint_t, uint_t, char *); 137 static void usba_dump_ep(uint_t, usb_ep_data_t *, usb_log_handle_t, uint_t, 138 uint_t, char *); 139 static void usba_dump_cv(usb_cvs_data_t *, usb_log_handle_t, uint_t, uint_t, 140 char *, int); 141 static void usba_dump_bin(uint8_t *, int, int, usb_log_handle_t, 142 uint_t, uint_t, char *, int); 143 144 /* Framework initialization. */ 145 void 146 usba_usbai_register_initialization() 147 { 148 usbai_reg_log_handle = usb_alloc_log_hdl(NULL, "usbreg", 149 &usbai_register_errlevel, 150 &usbai_register_errmask, NULL, 151 0); 152 153 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 154 "usba_usbai_register_initialization"); 155 } 156 157 158 /* Framework destruction. */ 159 void 160 usba_usbai_register_destroy() 161 { 162 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 163 "usba_usbai_register destroy"); 164 165 usb_free_log_hdl(usbai_reg_log_handle); 166 } 167 168 169 /* 170 * usb_client_attach: 171 * 172 * Arguments: 173 * dip - pointer to devinfo node of the client 174 * version - USBA registration version number 175 * flags - None used 176 * 177 * Return Values: 178 * USB_SUCCESS - attach succeeded 179 * USB_INVALID_ARGS - received null dip 180 * USB_INVALID_VERSION - version argument is incorrect. 181 * USB_FAILURE - other internal failure 182 */ 183 /*ARGSUSED*/ 184 int 185 usb_client_attach(dev_info_t *dip, uint_t version, usb_flags_t flags) 186 { 187 int rval; 188 usba_device_t *usba_device; 189 190 if (dip == NULL) { 191 192 return (USB_INVALID_ARGS); 193 } 194 195 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 196 "usb_client attach:"); 197 198 usba_device = usba_get_usba_device(dip); 199 200 /* 201 * Allow exact match for legacy (DDK 0.8/9) drivers, or same major 202 * VERSion and smaller or same minor version for non-legacy drivers. 203 */ 204 if ((version != 205 USBA_MAKE_VER(USBA_LEG_MAJOR_VER, USBA_LEG_MINOR_VER)) && 206 ((USBA_GET_MAJOR(version) != USBA_MAJOR_VER) || 207 (USBA_GET_MINOR(version) > USBA_MINOR_VER))) { 208 USB_DPRINTF_L1(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 209 "Incorrect USB driver version for %s%d: found: %d.%d, " 210 "expecting %d.%d", 211 ddi_driver_name(dip), ddi_get_instance(dip), 212 USBA_GET_MAJOR(version), USBA_GET_MINOR(version), 213 USBA_MAJOR_VER, USBA_MINOR_VER); 214 215 return (USB_INVALID_VERSION); 216 } 217 218 if (version == USBA_MAKE_VER(USBA_LEG_MAJOR_VER, USBA_LEG_MINOR_VER)) { 219 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 220 "Accepting legacy USB driver version %d.%d for %s%d", 221 USBA_LEG_MAJOR_VER, USBA_LEG_MINOR_VER, 222 ddi_driver_name(dip), ddi_get_instance(dip)); 223 } 224 225 rval = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "driver-major", 226 USBA_GET_MAJOR(version)); 227 if (rval != DDI_PROP_SUCCESS) { 228 229 return (USB_FAILURE); 230 } 231 rval = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "driver-minor", 232 USBA_GET_MINOR(version)); 233 if (rval != DDI_PROP_SUCCESS) { 234 235 return (USB_FAILURE); 236 } 237 238 mutex_enter(&usba_device->usb_mutex); 239 if (strcmp(ddi_driver_name(dip), "usb_mid") != 0) { 240 usba_device->usb_client_flags[usba_get_ifno(dip)] |= 241 USBA_CLIENT_FLAG_ATTACH; 242 usba_device->usb_client_attach_list->dip = dip; 243 } 244 mutex_exit(&usba_device->usb_mutex); 245 246 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 247 "usb_client attach: done"); 248 249 return (USB_SUCCESS); 250 } 251 252 253 /* 254 * usb_client_detach: 255 * free dev_data is reg != NULL, not much else to do 256 * 257 * Arguments: 258 * dip - pointer to devinfo node of the client 259 * reg - return registration data at this address 260 */ 261 void 262 usb_client_detach(dev_info_t *dip, usb_client_dev_data_t *reg) 263 { 264 usba_device_t *usba_device = usba_get_usba_device(dip); 265 266 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 267 "usb_client_detach:"); 268 269 if (dip) { 270 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 271 "Unregistering usb client %s%d: reg=0x%p", 272 ddi_driver_name(dip), ddi_get_instance(dip), (void *)reg); 273 274 usb_free_dev_data(dip, reg); 275 276 mutex_enter(&usba_device->usb_mutex); 277 if (strcmp(ddi_driver_name(dip), "usb_mid") != 0) { 278 usba_device->usb_client_flags[usba_get_ifno(dip)] &= 279 ~USBA_CLIENT_FLAG_ATTACH; 280 } 281 mutex_exit(&usba_device->usb_mutex); 282 } 283 284 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 285 "usb_client_detach done"); 286 } 287 288 289 /* 290 * usb_register_client (deprecated): 291 * The client registers with USBA during attach. 292 */ 293 /*ARGSUSED*/ 294 int 295 usb_register_client(dev_info_t *dip, uint_t version, 296 usb_client_dev_data_t **reg, usb_reg_parse_lvl_t parse_level, 297 usb_flags_t flags) 298 { 299 int rval = usb_client_attach(dip, version, flags); 300 301 if (rval == USB_SUCCESS) { 302 rval = usb_get_dev_data(dip, reg, parse_level, flags); 303 304 if (rval != USB_SUCCESS) { 305 usb_client_detach(dip, NULL); 306 } 307 } 308 309 return (rval); 310 } 311 312 313 /* 314 * usb_unregister_client (deprecated): 315 * Undo the makings of usb_get_dev_data(). Free memory if allocated. 316 * 317 * Arguments: 318 * dip - pointer to devinfo node of the client 319 * reg - pointer to registration data to be freed 320 */ 321 void 322 usb_unregister_client(dev_info_t *dip, usb_client_dev_data_t *reg) 323 { 324 usb_client_detach(dip, reg); 325 } 326 327 328 /* 329 * usb_get_dev_data: 330 * On completion, the registration data has been initialized. 331 * Most data items are straightforward. 332 * Among the items returned in the data is the tree of 333 * parsed descriptors, in dev_cfg; the number of configurations parsed, 334 * in dev_n_cfg; a pointer to the current configuration in the tree, 335 * in dev_curr_cfg; the index of the first valid interface in the 336 * tree, in dev_curr_if, and a parse level that accurately reflects what 337 * is in the tree, in dev_parse_level. 338 * 339 * This routine sets up directly-initialized fields, and calls 340 * usb_build_descr_tree() to parse the raw descriptors and initialize the 341 * tree. 342 * 343 * Parse_level determines the extent to which the tree is built. It has 344 * the following values: 345 * 346 * USB_PARSE_LVL_NONE - Build no tree. dev_n_cfg will return 0, dev_cfg 347 * and dev_curr_cfg will return NULL. 348 * USB_PARSE_LVL_IF - Parse configured interface only, if configuration# 349 * and interface properties are set (as when different 350 * interfaces are viewed by the OS as different device 351 * instances). If an OS device instance is set up to 352 * represent an entire physical device, this works 353 * like USB_PARSE_LVL_ALL. 354 * USB_PARSE_LVL_CFG - Parse entire configuration of configured interface 355 * only. This is like USB_PARSE_LVL_IF except entire 356 * configuration is returned. 357 * USB_PARSE_LVL_ALL - Parse entire device (all configurations), even 358 * when driver is bound to a single interface of a 359 * single configuration. 360 * 361 * No tree is built for root hubs, regardless of parse_level. 362 * 363 * Arguments: 364 * dip - pointer to devinfo node of the client 365 * version - USBA registration version number 366 * reg - return registration data at this address 367 * parse_level - See above 368 * flags - None used 369 * 370 * Return Values: 371 * USB_SUCCESS - usb_get_dev_data succeeded 372 * USB_INVALID_ARGS - received null dip or reg argument 373 * USB_INVALID_CONTEXT - called from callback context 374 * USB_FAILURE - bad descriptor info or other internal failure 375 * 376 * Note: The non-standard USB descriptors are returned in RAW format. 377 * returns initialized registration data. Most data items are clear. 378 * Among the items returned is the tree of parsed descriptors in dev_cfg; 379 * and the number of configurations parsed in dev_n_cfg. 380 * 381 * The registration data is not shared. each client receives its own 382 * copy. 383 */ 384 /*ARGSUSED*/ 385 int 386 usb_get_dev_data(dev_info_t *dip, 387 usb_client_dev_data_t **reg, usb_reg_parse_lvl_t parse_level, 388 usb_flags_t flags) 389 { 390 usb_client_dev_data_t *usb_reg = NULL; 391 char *tmpbuf = NULL; 392 usba_device_t *usba_device; 393 int rval = USB_SUCCESS; 394 395 if ((dip == NULL) || (reg == NULL)) { 396 397 return (USB_INVALID_ARGS); 398 } 399 400 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 401 "usb_get_dev_data: %s%d", 402 ddi_driver_name(dip), ddi_get_instance(dip)); 403 404 *reg = NULL; 405 406 /* did the client attach first? */ 407 if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 408 "driver-major", -1) == -1) { 409 410 return (USB_INVALID_VERSION); 411 } 412 if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 413 "driver-minor", -1) == -1) { 414 415 return (USB_INVALID_VERSION); 416 } 417 418 usb_reg = kmem_zalloc(sizeof (usb_client_dev_data_t), KM_SLEEP); 419 usba_device = usba_get_usba_device(dip); 420 usb_reg->dev_descr = usba_device->usb_dev_descr; 421 usb_reg->dev_default_ph = usba_get_dflt_pipe_handle(dip); 422 if (usb_reg->dev_default_ph == NULL) { 423 kmem_free(usb_reg, sizeof (usb_client_dev_data_t)); 424 425 return (USB_FAILURE); 426 } 427 428 usb_reg->dev_iblock_cookie = usba_hcdi_get_hcdi( 429 usba_device->usb_root_hub_dip)->hcdi_soft_iblock_cookie; 430 431 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 432 "cookie = 0x%p", (void *)usb_reg->dev_iblock_cookie); 433 434 tmpbuf = (char *)kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP); 435 436 if (usba_device->usb_mfg_str != NULL) { 437 usb_reg->dev_mfg = kmem_zalloc( 438 strlen(usba_device->usb_mfg_str) + 1, KM_SLEEP); 439 (void) strcpy(usb_reg->dev_mfg, usba_device->usb_mfg_str); 440 } 441 442 if (usba_device->usb_product_str != NULL) { 443 usb_reg->dev_product = kmem_zalloc( 444 strlen(usba_device->usb_product_str) + 1, 445 KM_SLEEP); 446 (void) strcpy(usb_reg->dev_product, 447 usba_device->usb_product_str); 448 } 449 450 if (usba_device->usb_serialno_str != NULL) { 451 usb_reg->dev_serial = kmem_zalloc( 452 strlen(usba_device->usb_serialno_str) + 1, 453 KM_SLEEP); 454 (void) strcpy(usb_reg->dev_serial, 455 usba_device->usb_serialno_str); 456 } 457 458 if ((usb_reg->dev_parse_level = parse_level) == USB_PARSE_LVL_NONE) { 459 rval = USB_SUCCESS; 460 461 } else if ((rval = usba_build_descr_tree(dip, usba_device, usb_reg)) != 462 USB_SUCCESS) { 463 usb_unregister_client(dip, usb_reg); 464 usb_reg = NULL; 465 } else { 466 467 /* Current tree cfg is always zero if only one cfg in tree. */ 468 if (usb_reg->dev_n_cfg == 1) { 469 usb_reg->dev_curr_cfg = &usb_reg->dev_cfg[0]; 470 } else { 471 mutex_enter(&usba_device->usb_mutex); 472 usb_reg->dev_curr_cfg = 473 &usb_reg->dev_cfg[usba_device->usb_active_cfg_ndx]; 474 mutex_exit(&usba_device->usb_mutex); 475 ASSERT(usb_reg->dev_curr_cfg != NULL); 476 ASSERT(usb_reg->dev_curr_cfg->cfg_descr.bLength == 477 USB_CFG_DESCR_SIZE); 478 } 479 480 /* 481 * Keep dev_curr_if at device's single interface only if that 482 * particular interface has been explicitly defined by the 483 * device. 484 */ 485 usb_reg->dev_curr_if = usba_get_ifno(dip); 486 #ifdef DEBUG 487 (void) usb_log_descr_tree(usb_reg, usbai_reg_log_handle, 488 usbai_register_dump_errlevel, (uint_t)-1); 489 #endif 490 /* 491 * Fail if interface and configuration of dev_curr_if and 492 * dev_curr_cfg don't exist or are invalid. (Shouldn't happen.) 493 * These indices must be reliable for tree traversal. 494 */ 495 if ((usb_reg->dev_curr_cfg->cfg_n_if <= usb_reg->dev_curr_if) || 496 (usb_reg->dev_curr_cfg->cfg_descr.bLength == 0) || 497 (usb_reg->dev_curr_cfg->cfg_if[usb_reg->dev_curr_if]. 498 if_n_alt == 0)) { 499 USB_DPRINTF_L2(DPRINT_MASK_ALL, usbai_reg_log_handle, 500 "usb_get_dev_data: dev_curr_cfg or " 501 "dev_curr_if have no descriptors"); 502 usb_unregister_client(dip, usb_reg); 503 usb_reg = NULL; 504 rval = USB_FAILURE; 505 } 506 } 507 508 *reg = usb_reg; 509 kmem_free(tmpbuf, USB_MAXSTRINGLEN); 510 511 if (rval == USB_SUCCESS) { 512 usb_client_dev_data_list_t *entry = kmem_zalloc( 513 sizeof (*entry), KM_SLEEP); 514 mutex_enter(&usba_device->usb_mutex); 515 516 usba_device->usb_client_flags[usba_get_ifno(dip)] |= 517 USBA_CLIENT_FLAG_DEV_DATA; 518 519 entry->cddl_dip = dip; 520 entry->cddl_dev_data = usb_reg; 521 entry->cddl_ifno = usba_get_ifno(dip); 522 523 entry->cddl_next = 524 usba_device->usb_client_dev_data_list.cddl_next; 525 if (entry->cddl_next) { 526 entry->cddl_next->cddl_prev = entry; 527 } 528 entry->cddl_prev = &usba_device->usb_client_dev_data_list; 529 usba_device->usb_client_dev_data_list.cddl_next = entry; 530 531 mutex_exit(&usba_device->usb_mutex); 532 } 533 534 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 535 "usb_get_dev_data rval=%d", rval); 536 537 return (rval); 538 } 539 540 541 /* 542 * usb_free_dev_data 543 * undoes what usb_get_dev_data does 544 * 545 * Arguments: 546 * dip - pointer to devinfo node of the client 547 * reg - return registration data at this address 548 */ 549 void 550 usb_free_dev_data(dev_info_t *dip, usb_client_dev_data_t *reg) 551 { 552 if (dip == NULL) { 553 554 return; 555 } 556 557 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 558 "usb_free_dev_data %s%d: reg=0x%p", 559 ddi_driver_name(dip), ddi_get_instance(dip), (void *)reg); 560 561 if (reg != NULL) { 562 usba_device_t *usba_device = usba_get_usba_device(dip); 563 usb_client_dev_data_list_t *next, *prev, *entry; 564 int matches = 0; 565 566 if (reg->dev_serial != NULL) { 567 kmem_free((char *)reg->dev_serial, 568 strlen((char *)reg->dev_serial) + 1); 569 } 570 571 if (reg->dev_product != NULL) { 572 kmem_free((char *)reg->dev_product, 573 strlen((char *)reg->dev_product) + 1); 574 } 575 576 if (reg->dev_mfg != NULL) { 577 kmem_free((char *)reg->dev_mfg, 578 strlen((char *)reg->dev_mfg) + 1); 579 } 580 581 /* Free config tree under reg->dev_cfg. */ 582 if (reg->dev_cfg != NULL) { 583 usb_free_descr_tree(dip, reg); 584 } 585 586 mutex_enter(&usba_device->usb_mutex); 587 prev = &usba_device->usb_client_dev_data_list; 588 entry = usba_device->usb_client_dev_data_list.cddl_next; 589 590 /* free the entries in usb_client_data_list */ 591 while (entry) { 592 next = entry->cddl_next; 593 if ((dip == entry->cddl_dip) && 594 (reg == entry->cddl_dev_data)) { 595 prev->cddl_next = entry->cddl_next; 596 if (entry->cddl_next) { 597 entry->cddl_next->cddl_prev = prev; 598 } 599 kmem_free(entry, sizeof (*entry)); 600 } else { 601 /* 602 * any other entries for this interface? 603 */ 604 if (usba_get_ifno(dip) == entry->cddl_ifno) { 605 matches++; 606 } 607 prev = entry; 608 } 609 entry = next; 610 } 611 612 USB_DPRINTF_L3(DPRINT_MASK_REGISTER, 613 usbai_reg_log_handle, 614 "usb_free_dev_data: next=0x%p flags[%d]=0x%x", 615 (void *)usba_device->usb_client_dev_data_list.cddl_next, 616 usba_get_ifno(dip), 617 usba_device->usb_client_flags[usba_get_ifno(dip)]); 618 619 if (matches == 0) { 620 usba_device-> 621 usb_client_flags[usba_get_ifno(dip)] &= 622 ~USBA_CLIENT_FLAG_DEV_DATA; 623 } 624 mutex_exit(&usba_device->usb_mutex); 625 626 kmem_free(reg, sizeof (usb_client_dev_data_t)); 627 } 628 629 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 630 "usb_free_dev_data done"); 631 } 632 633 634 /* 635 * usba_build_descr_tree: 636 * This builds the descriptor tree. See module header comment for tree 637 * description. 638 * 639 * Arguments: 640 * dip - devinfo pointer - cannot be NULL. 641 * usba_device - pointer to usba_device structure. 642 * usb_reg - pointer to area returned to client describing device. 643 * number of configuration (dev_n_cfg) and array of 644 * configurations (dev_cfg) are initialized here - 645 * dev_parse_level used and may be modified to fit 646 * current configuration. 647 * Return values: 648 * USB_SUCCESS - Tree build succeeded 649 * USB_INVALID_ARGS - dev_parse_level in usb_reg is invalid. 650 * USB_FAILURE - Bad descriptor info or other internal failure 651 */ 652 static int 653 usba_build_descr_tree(dev_info_t *dip, usba_device_t *usba_device, 654 usb_client_dev_data_t *usb_reg) 655 { 656 usba_reg_state_t state; /* State of tree construction */ 657 int cfg_len_so_far = 0; /* Bytes found, this config. */ 658 uint8_t *last_byte; /* Ptr to the end of the cfg cloud. */ 659 uint_t this_cfg_ndx; /* Configuration counter. */ 660 uint_t high_cfg_bound; /* High config index + 1. */ 661 uint_t low_cfg_bound; /* Low config index. */ 662 boolean_t process_this_if_tree = B_FALSE; /* Save alts, eps, */ 663 /* of this interface. */ 664 665 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 666 "usba_build_descr_tree starting"); 667 668 bzero(&state, sizeof (usba_reg_state_t)); 669 state.dip = dip; 670 671 /* 672 * Set config(s) and interface(s) to parse based on parse level. 673 * Adjust parse_level according to which configs and interfaces are 674 * made available by the device. 675 */ 676 state.st_dev_parse_level = usb_reg->dev_parse_level; 677 if (usba_set_parse_values(dip, usba_device, &state) != USB_SUCCESS) { 678 679 return (USB_INVALID_ARGS); 680 } 681 usb_reg->dev_parse_level = state.st_dev_parse_level; 682 683 /* Preallocate configurations based on parse level. */ 684 if (usb_reg->dev_parse_level == USB_PARSE_LVL_ALL) { 685 usb_reg->dev_n_cfg = usba_device->usb_n_cfgs; 686 low_cfg_bound = 0; 687 high_cfg_bound = usba_device->usb_n_cfgs; 688 } else { 689 usb_reg->dev_n_cfg = 1; 690 mutex_enter(&usba_device->usb_mutex); 691 low_cfg_bound = usba_device->usb_active_cfg_ndx; 692 high_cfg_bound = usba_device->usb_active_cfg_ndx + 1; 693 mutex_exit(&usba_device->usb_mutex); 694 } 695 usb_reg->dev_cfg = state.st_dev_cfg = kmem_zalloc( 696 (usb_reg->dev_n_cfg * sizeof (usb_cfg_data_t)), 697 KM_SLEEP); 698 /* 699 * this_cfg_ndx loops through all configurations presented; 700 * state.st_dev_n_cfg limits the cfgs checked to the number desired. 701 */ 702 state.st_dev_n_cfg = 0; 703 for (this_cfg_ndx = low_cfg_bound; this_cfg_ndx < high_cfg_bound; 704 this_cfg_ndx++) { 705 706 state.st_curr_raw_descr = 707 usba_device->usb_cfg_array[this_cfg_ndx]; 708 ASSERT(state.st_curr_raw_descr != NULL); 709 710 /* Clear the following for config cloud sanity checking. */ 711 last_byte = NULL; 712 state.st_curr_cfg = NULL; 713 state.st_curr_if = NULL; 714 state.st_curr_alt = NULL; 715 state.st_curr_ep = NULL; 716 717 do { 718 /* All descr have length and type at offset 0 and 1 */ 719 state.st_curr_raw_descr_len = 720 state.st_curr_raw_descr[0]; 721 state.st_curr_raw_descr_type = 722 state.st_curr_raw_descr[1]; 723 724 /* First descr in cloud must be a config descr. */ 725 if ((last_byte == NULL) && 726 (state.st_curr_raw_descr_type != 727 USB_DESCR_TYPE_CFG)) { 728 729 return (USB_FAILURE); 730 } 731 732 /* 733 * Bomb if we don't find a new cfg descr when expected. 734 * cfg_len_so_far = total_cfg_length = 0 1st time thru. 735 */ 736 if (cfg_len_so_far > state.st_total_cfg_length) { 737 USB_DPRINTF_L2(DPRINT_MASK_ALL, 738 usbai_reg_log_handle, 739 "usba_build_descr_tree: Configuration (%d) " 740 "larger than wTotalLength (%d).", 741 cfg_len_so_far, state.st_total_cfg_length); 742 743 return (USB_FAILURE); 744 } 745 746 USB_DPRINTF_L3(DPRINT_MASK_REGISTER, 747 usbai_reg_log_handle, 748 "usba_build_descr_tree: Process type %d descr " 749 "(addr=0x%p)", state.st_curr_raw_descr_type, 750 (void *)state.st_curr_raw_descr); 751 752 switch (state.st_curr_raw_descr_type) { 753 case USB_DESCR_TYPE_CFG: 754 cfg_len_so_far = 0; 755 process_this_if_tree = B_FALSE; 756 757 state.st_curr_cfg_str = usba_device-> 758 usb_cfg_str_descr[this_cfg_ndx]; 759 usba_process_cfg_descr(&state); 760 state.st_last_processed_descr_type = 761 USB_DESCR_TYPE_CFG; 762 last_byte = state.st_curr_raw_descr + 763 (state.st_total_cfg_length * 764 sizeof (uchar_t)); 765 766 break; 767 768 case USB_DESCR_TYPE_IF: 769 /* 770 * process_this_if_tree == TRUE means this 771 * interface, plus all eps and c/vs in it are 772 * to be processed. 773 */ 774 if (usba_process_if_descr(&state, 775 &process_this_if_tree) != USB_SUCCESS) { 776 777 return (USB_FAILURE); 778 } 779 state.st_last_processed_descr_type = 780 USB_DESCR_TYPE_IF; 781 782 break; 783 784 case USB_DESCR_TYPE_EP: 785 /* 786 * Skip if endpoints of a specific interface are 787 * desired and this endpoint is associated with 788 * a different interface. 789 */ 790 if (process_this_if_tree) { 791 if (usba_process_ep_descr(&state) != 792 USB_SUCCESS) { 793 794 return (USB_FAILURE); 795 } 796 state.st_last_processed_descr_type = 797 USB_DESCR_TYPE_EP; 798 } 799 800 break; 801 802 case USB_DESCR_TYPE_STRING: 803 USB_DPRINTF_L2(DPRINT_MASK_ALL, 804 usbai_reg_log_handle, 805 "usb_get_dev_data: " 806 "Found unexpected str descr at addr 0x%p", 807 (void *)state.st_curr_raw_descr); 808 809 break; /* Shouldn't be any here. Skip. */ 810 811 default: 812 /* 813 * Treat all other descr as class/vendor 814 * specific. Skip if c/vs of a specific 815 * interface are desired and this c/v is 816 * associated with a different one. 817 */ 818 if (process_this_if_tree == B_TRUE) { 819 if (usba_process_cv_descr(&state) != 820 USB_SUCCESS) { 821 822 return (USB_FAILURE); 823 } 824 } 825 } 826 827 state.st_curr_raw_descr += state.st_curr_raw_descr_len; 828 cfg_len_so_far += state.st_curr_raw_descr_len; 829 830 } while (state.st_curr_raw_descr < last_byte); 831 } 832 833 /* Make tree sparse, and put elements in order. */ 834 usba_order_tree(&state); 835 836 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 837 "usba_build_descr_tree done"); 838 839 return (USB_SUCCESS); 840 } 841 842 843 /* 844 * usba_process_cfg_descr: 845 * Set up a configuration tree node based on a raw config descriptor. 846 * 847 * Arguments: 848 * state - Pointer to this module's state structure. 849 * 850 * Returns: 851 * B_TRUE: the descr processed corresponds to a requested configuration. 852 * B_FALSE: the descr processed does not correspond to a requested config. 853 */ 854 static void 855 usba_process_cfg_descr(usba_reg_state_t *state) 856 { 857 usb_cfg_data_t *curr_cfg; 858 859 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 860 "usba_process_cfg_descr starting"); 861 862 curr_cfg = state->st_curr_cfg = 863 &state->st_dev_cfg[state->st_dev_n_cfg++]; 864 865 /* Parse and store config descriptor proper in the tree. */ 866 (void) usb_parse_data("2cs5c", 867 state->st_curr_raw_descr, state->st_curr_raw_descr_len, 868 &curr_cfg->cfg_descr, 869 sizeof (usb_cfg_descr_t)); 870 871 state->st_total_cfg_length = curr_cfg->cfg_descr.wTotalLength; 872 873 if (state->st_curr_cfg_str != NULL) { 874 curr_cfg->cfg_strsize = strlen(state->st_curr_cfg_str) + 1; 875 curr_cfg->cfg_str = kmem_zalloc(curr_cfg->cfg_strsize, 876 KM_SLEEP); 877 (void) strcpy(curr_cfg->cfg_str, state->st_curr_cfg_str); 878 } 879 880 curr_cfg->cfg_n_if = curr_cfg->cfg_descr.bNumInterfaces; 881 curr_cfg->cfg_if = kmem_zalloc((curr_cfg->cfg_n_if * 882 sizeof (usb_if_data_t)), KM_SLEEP); 883 884 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 885 "usba_process_cfg_descr done"); 886 } 887 888 889 /* 890 * usba_process_if_descr: 891 * This processes a raw interface descriptor, and sets up an analogous 892 * interface node and child "alternate" nodes (each containing an 893 * interface descriptor) in the descriptor tree. 894 * 895 * It groups all descriptors with the same bInterfaceNumber (alternates) 896 * into an array. It makes entries in an interface array, each of which 897 * points to an array of alternates. 898 * 899 * Arguments: 900 * state - Pointer to this module's state structure. 901 * requested_if - Address into which the following is returned: 902 * B_TRUE - the processed descr is of a requested interface. 903 * B_FALSE - the processed descr if of a non-requested interface. 904 * 905 * Returns: 906 * USB_SUCCESS: Descriptor is successfully parsed. 907 * USB_FAILURE: Descriptor is inappropriately placed in config cloud. 908 */ 909 static int 910 usba_process_if_descr(usba_reg_state_t *state, boolean_t *requested_if) 911 { 912 char *string; 913 usb_if_descr_t *new_if_descr; 914 usba_device_t *usba_device = usba_get_usba_device(state->dip); 915 int is_root_hub = (usba_device->usb_addr == ROOT_HUB_ADDR); 916 917 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 918 "usba_process_if_descr starting"); 919 920 /* No config preceeds this interface. */ 921 if (state->st_curr_cfg == NULL) { 922 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 923 "usba_process_if_descr found interface after no config."); 924 925 return (USB_FAILURE); 926 } 927 928 new_if_descr = kmem_zalloc(sizeof (usb_if_descr_t), KM_SLEEP); 929 930 /* Strictly speaking, unpacking is not necessary. Could use bcopy. */ 931 (void) usb_parse_data("9c", state->st_curr_raw_descr, 932 state->st_curr_raw_descr_len, 933 new_if_descr, sizeof (usb_if_descr_t)); 934 935 /* Check the interface number in case of a malfunction device */ 936 if (new_if_descr->bInterfaceNumber >= state->st_curr_cfg->cfg_n_if) { 937 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 938 "usba_process_if_descr: bInterfaceNumber=%d is not " 939 "a valid one", new_if_descr->bInterfaceNumber); 940 kmem_free(new_if_descr, sizeof (usb_if_descr_t)); 941 942 *requested_if = B_FALSE; 943 944 return (USB_SUCCESS); 945 } 946 *requested_if = B_TRUE; 947 948 /* Not a requested interface. */ 949 if ((state->st_if_to_build != new_if_descr->bInterfaceNumber) && 950 (state->st_if_to_build != USBA_ALL)) { 951 *requested_if = B_FALSE; 952 953 } else { 954 usb_alt_if_data_t *alt_array; 955 uint_t alt_index; 956 957 /* Point to proper interface node, based on num in descr. */ 958 state->st_curr_if = 959 &state->st_curr_cfg->cfg_if[new_if_descr->bInterfaceNumber]; 960 961 /* Make room for new alternate. */ 962 alt_index = state->st_curr_if->if_n_alt; 963 alt_array = state->st_curr_if->if_alt; 964 usba_augment_array((void **)(&alt_array), alt_index, 965 sizeof (usb_alt_if_data_t)); 966 967 /* Ptr to the current alt, may be used to attach a c/v to it. */ 968 state->st_curr_alt = &alt_array[alt_index]; 969 970 bcopy(new_if_descr, &(alt_array[alt_index++].altif_descr), 971 sizeof (usb_if_descr_t)); 972 state->st_curr_if->if_alt = alt_array; 973 state->st_curr_if->if_n_alt = alt_index; 974 975 string = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP); 976 if (!is_root_hub) { 977 (void) usb_get_string_descr(state->dip, USB_LANG_ID, 978 state->st_curr_alt->altif_descr.iInterface, 979 string, USB_MAXSTRINGLEN); 980 } 981 if (string[0] == '\0') { 982 (void) strcpy(string, "<none>"); 983 } 984 state->st_curr_alt->altif_strsize = strlen(string) + 1; 985 state->st_curr_alt->altif_str = kmem_zalloc( 986 state->st_curr_alt->altif_strsize, KM_SLEEP); 987 (void) strcpy(state->st_curr_alt->altif_str, string); 988 kmem_free(string, USB_MAXSTRINGLEN); 989 } 990 991 kmem_free(new_if_descr, sizeof (usb_if_descr_t)); 992 993 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 994 "usba_process_if_descr done"); 995 996 return (USB_SUCCESS); 997 } 998 999 1000 /* 1001 * usba_process_ep_descr: 1002 * This processes a raw endpoint descriptor, and sets up an analogous 1003 * endpoint descriptor node in the descriptor tree. 1004 * 1005 * Arguments: 1006 * state - Pointer to this module's state structure. 1007 * 1008 * Returns: 1009 * USB_SUCCESS: Descriptor is successfully parsed. 1010 * USB_FAILURE: Descriptor is inappropriately placed in config cloud. 1011 */ 1012 static int 1013 usba_process_ep_descr(usba_reg_state_t *state) 1014 { 1015 usb_alt_if_data_t *curr_alt = state->st_curr_alt; 1016 1017 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1018 "usba_process_ep_descr starting"); 1019 1020 /* No interface preceeds this endpoint. */ 1021 if (state->st_curr_alt == NULL) { 1022 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1023 "usba_process_ep_descr: no requested alt before endpt."); 1024 1025 return (USB_FAILURE); 1026 } 1027 1028 usba_augment_array((void **)(&curr_alt->altif_ep), 1029 curr_alt->altif_n_ep, sizeof (usb_ep_data_t)); 1030 1031 /* Ptr to the current endpt, may be used to attach a c/v to it. */ 1032 state->st_curr_ep = &curr_alt->altif_ep[curr_alt->altif_n_ep++]; 1033 1034 (void) usb_parse_data("4csc", state->st_curr_raw_descr, 1035 state->st_curr_raw_descr_len, 1036 &state->st_curr_ep->ep_descr, sizeof (usb_ep_descr_t)); 1037 1038 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1039 "usba_process_ep_descr done"); 1040 1041 return (USB_SUCCESS); 1042 } 1043 1044 1045 /* 1046 * usba_process_cv_descr: 1047 * This processes a raw endpoint descriptor, and sets up an analogous 1048 * endpoint descriptor in the descriptor tree. C/Vs are associated with 1049 * other descriptors they follow in the raw data. 1050 * last_processed_descr_type indicates the type of descr this c/v follows. 1051 * 1052 * Arguments: 1053 * state - Pointer to this module's state structure. 1054 * 1055 * Returns: 1056 * USB_SUCCESS: Descriptor is successfully parsed. 1057 * USB_FAILURE: Descriptor is inappropriately placed in config cloud. 1058 */ 1059 static int 1060 usba_process_cv_descr(usba_reg_state_t *state) 1061 { 1062 usb_cvs_data_t *curr_cv_descr; 1063 usb_cvs_data_t **cvs_ptr = NULL; 1064 uint_t *n_cvs_ptr; 1065 1066 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1067 "usba_process_cv_descr starting. Processing c/v for descr type %d", 1068 state->st_last_processed_descr_type); 1069 1070 /* 1071 * Attach the c/v to a node based on the last descr type processed. 1072 * Save handles to appropriate c/v node array and count to update. 1073 */ 1074 switch (state->st_last_processed_descr_type) { 1075 case USB_DESCR_TYPE_CFG: 1076 n_cvs_ptr = &state->st_curr_cfg->cfg_n_cvs; 1077 cvs_ptr = &state->st_curr_cfg->cfg_cvs; 1078 break; 1079 1080 case USB_DESCR_TYPE_IF: 1081 n_cvs_ptr = &state->st_curr_alt->altif_n_cvs; 1082 cvs_ptr = &state->st_curr_alt->altif_cvs; 1083 break; 1084 1085 case USB_DESCR_TYPE_EP: 1086 n_cvs_ptr = &state->st_curr_ep->ep_n_cvs; 1087 cvs_ptr = &state->st_curr_ep->ep_cvs; 1088 break; 1089 1090 default: 1091 USB_DPRINTF_L2(DPRINT_MASK_ALL, usbai_reg_log_handle, 1092 "usba_process_cv_descr: Type of last descriptor unknown. "); 1093 1094 return (USB_FAILURE); 1095 } 1096 1097 usba_augment_array((void **)cvs_ptr, *n_cvs_ptr, 1098 sizeof (usb_cvs_data_t)); 1099 curr_cv_descr = &(*cvs_ptr)[(*n_cvs_ptr)++]; 1100 1101 curr_cv_descr->cvs_buf = 1102 kmem_zalloc(state->st_curr_raw_descr_len, KM_SLEEP); 1103 curr_cv_descr->cvs_buf_len = state->st_curr_raw_descr_len; 1104 bcopy(state->st_curr_raw_descr, curr_cv_descr->cvs_buf, 1105 state->st_curr_raw_descr_len); 1106 1107 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1108 "usba_process_cv_descr done"); 1109 1110 return (USB_SUCCESS); 1111 } 1112 1113 1114 /* 1115 * usba_set_parse_values: 1116 * Based on parse level, set the configuration(s) and interface(s) to build 1117 * 1118 * Returned configuration value can be USBA_ALL indicating to build all 1119 * configurations. Likewise for the returned interface value. 1120 * 1121 * Arguments: 1122 * dip - pointer to devinfo of the device 1123 * usba_device - pointer to usba_device structure of the device 1124 * state - Pointer to this module's state structure. 1125 * if no specific config specified, default to all config 1126 * if no specific interface specified, default to all. 1127 * if_to_build and config_to_build are modified. 1128 * dev_parse_level may be modified. 1129 * 1130 * Returns: 1131 * USB_SUCCESS - success 1132 * USB_INVALID_ARGS - state->st_dev_parse_level is invalid. 1133 */ 1134 static int 1135 usba_set_parse_values(dev_info_t *dip, usba_device_t *usba_device, 1136 usba_reg_state_t *state) 1137 { 1138 /* Default to *all* in case configuration# prop not set. */ 1139 mutex_enter(&usba_device->usb_mutex); 1140 state->st_cfg_to_build = usba_device->usb_active_cfg_ndx; 1141 mutex_exit(&usba_device->usb_mutex); 1142 if (state->st_cfg_to_build == USBA_DEV_CONFIG_INDEX_UNDEFINED) { 1143 state->st_cfg_to_build = USBA_ALL; 1144 } 1145 state->st_if_to_build = usb_get_if_number(dip); 1146 1147 switch (state->st_dev_parse_level) { 1148 case USB_PARSE_LVL_ALL: /* Parse all configurations */ 1149 state->st_cfg_to_build = USBA_ALL; 1150 state->st_if_to_build = USBA_ALL; 1151 break; 1152 1153 case USB_PARSE_LVL_CFG: /* Parse all interfaces of a */ 1154 /* specific configuration. */ 1155 state->st_if_to_build = USBA_ALL; 1156 break; 1157 1158 case USB_PARSE_LVL_IF: /* Parse configured interface only */ 1159 if (state->st_if_to_build < 0) { 1160 state->st_if_to_build = USBA_ALL; 1161 } 1162 break; 1163 1164 default: 1165 1166 return (USB_INVALID_ARGS); 1167 } 1168 1169 /* 1170 * Set parse level to identify this tree properly, regardless of what 1171 * the caller thought the tree would have. 1172 */ 1173 if ((state->st_if_to_build == USBA_ALL) && 1174 (state->st_dev_parse_level == USB_PARSE_LVL_IF)) { 1175 state->st_dev_parse_level = USB_PARSE_LVL_CFG; 1176 } 1177 if ((state->st_cfg_to_build == USBA_ALL) && 1178 (state->st_dev_parse_level == USB_PARSE_LVL_CFG)) { 1179 state->st_dev_parse_level = USB_PARSE_LVL_ALL; 1180 } 1181 1182 return (USB_SUCCESS); 1183 } 1184 1185 1186 /* 1187 * usba_kmem_realloc: 1188 * Resize dynamic memory. Copy contents of old area to 1189 * beginning of new area. 1190 * 1191 * Arguments: 1192 * old_mem - pointer to old memory area. 1193 * old_size - size of old memory area. 0 is OK. 1194 * new_size - size desired. 1195 * 1196 * Returns: 1197 * pointer to new memory area. 1198 */ 1199 static void* 1200 usba_kmem_realloc(void* old_mem, int old_size, int new_size) 1201 { 1202 void *new_mem = NULL; 1203 1204 if (new_size > 0) { 1205 new_mem = kmem_zalloc(new_size, KM_SLEEP); 1206 if (old_size > 0) { 1207 bcopy(old_mem, new_mem, 1208 min(old_size, new_size)); 1209 } 1210 } 1211 1212 if (old_size > 0) { 1213 kmem_free(old_mem, old_size); 1214 } 1215 1216 return (new_mem); 1217 } 1218 1219 1220 /* 1221 * usba_augment_array: 1222 * Add a new element on the end of an array. 1223 * 1224 * Arguments: 1225 * addr - ptr to the array address. Array addr will change. 1226 * n_elements - array element count. 1227 * element_size - size of an array element 1228 */ 1229 static void 1230 usba_augment_array(void **addr, uint_t n_elements, uint_t element_size) 1231 { 1232 *addr = usba_kmem_realloc(*addr, (n_elements * element_size), 1233 ((n_elements + 1) * element_size)); 1234 } 1235 1236 1237 /* 1238 * usba_make_alts_sparse: 1239 * Disburse alternate array elements such that they are at the proper array 1240 * indices for which alt they represent. It is assumed that all key values 1241 * used for ordering the elements are positive. Original array space may 1242 * be freed and new space allocated. 1243 * 1244 * Arguments: 1245 * array - pointer to alternates array; may be modified 1246 * n_elements - number of elements in the array; may be modified 1247 */ 1248 static void 1249 usba_make_alts_sparse(usb_alt_if_data_t **array, uint_t *n_elements) 1250 { 1251 uint_t n_orig_elements = *n_elements; 1252 uint8_t smallest_value; 1253 uint8_t largest_value; 1254 uint8_t curr_value; 1255 uint_t in_order = 0; 1256 usb_alt_if_data_t *orig_addr = *array; /* Non-sparse array base ptr */ 1257 usb_alt_if_data_t *repl_array; /* Base ptr to sparse array */ 1258 uint_t n_repl_elements; /* Number elements in the new array */ 1259 uint_t i; 1260 1261 /* Check for a null array. */ 1262 if ((array == NULL) || (n_orig_elements == 0)) { 1263 1264 return; 1265 } 1266 1267 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1268 "make_sparse: array=0x%p, n_orig_elements=%d", 1269 (void *)array, n_orig_elements); 1270 1271 curr_value = orig_addr[0].altif_descr.bAlternateSetting; 1272 smallest_value = largest_value = curr_value; 1273 1274 /* Figure the low-high range of the array. */ 1275 for (i = 1; i < n_orig_elements; i++) { 1276 curr_value = orig_addr[i].altif_descr.bAlternateSetting; 1277 if (curr_value < smallest_value) { 1278 smallest_value = curr_value; 1279 } else if (curr_value > largest_value) { 1280 in_order++; 1281 largest_value = curr_value; 1282 } 1283 } 1284 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1285 "make_sparse: largest=%d, smallest=%d, " 1286 "order=%d", 1287 largest_value, smallest_value, in_order); 1288 1289 n_repl_elements = largest_value + 1; 1290 1291 /* 1292 * No holes to leave, array starts at zero, and everything is already 1293 * in order. Just return original array. 1294 */ 1295 if ((n_repl_elements == n_orig_elements) && 1296 ((in_order + 1) == n_orig_elements)) { 1297 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1298 "No holes"); 1299 1300 return; 1301 } 1302 1303 /* Allocate zeroed space for the array. */ 1304 repl_array = kmem_zalloc( 1305 (n_repl_elements * sizeof (usb_alt_if_data_t)), KM_SLEEP); 1306 1307 /* Now fill in the array. */ 1308 for (i = 0; i < n_orig_elements; i++) { 1309 curr_value = orig_addr[i].altif_descr.bAlternateSetting; 1310 1311 /* Place in sparse array based on key. */ 1312 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1313 "move %lu bytes (key %d) from 0x%p to 0x%p", 1314 (unsigned long)sizeof (usb_alt_if_data_t), curr_value, 1315 (void *)&orig_addr[i], (void *)&repl_array[curr_value]); 1316 1317 bcopy((char *)&orig_addr[i], (char *)&repl_array[curr_value], 1318 sizeof (usb_alt_if_data_t)); 1319 } 1320 1321 kmem_free(*array, sizeof (usb_alt_if_data_t) * n_orig_elements); 1322 *array = repl_array; 1323 *n_elements = n_repl_elements; 1324 } 1325 1326 1327 /* 1328 * usba_order_tree: 1329 * Take a tree as built by usba_build_descr_tree and make sure the key 1330 * values of all elements match their indeces. Proper order is implied. 1331 * 1332 * Arguments: 1333 * state - Pointer to this module's state structure. 1334 */ 1335 static void 1336 usba_order_tree(usba_reg_state_t *state) 1337 { 1338 usb_cfg_data_t *this_cfg; 1339 usb_if_data_t *this_if; 1340 uint_t n_cfgs = state->st_dev_n_cfg; 1341 uint_t cfg; 1342 uint_t which_if; 1343 1344 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1345 "usba_order_tree:"); 1346 1347 for (cfg = 0; cfg < n_cfgs; cfg++) { 1348 this_cfg = &state->st_dev_cfg[cfg]; 1349 1350 for (which_if = 0; which_if < this_cfg->cfg_n_if; which_if++) { 1351 this_if = this_cfg->cfg_if; 1352 usba_make_alts_sparse(&this_if->if_alt, 1353 &this_if->if_n_alt); 1354 } 1355 } 1356 } 1357 1358 1359 /* 1360 * usb_free_descr_tree: 1361 * Take down the configuration tree. Called internally and can be called 1362 * from a driver standalone to take the tree down while leaving the rest 1363 * of the registration intact. 1364 * 1365 * Arguments: 1366 * dip - pointer to devinfo of the device 1367 * dev_data - pointer to registration data containing the tree. 1368 */ 1369 void 1370 usb_free_descr_tree(dev_info_t *dip, usb_client_dev_data_t *dev_data) 1371 { 1372 usb_cfg_data_t *cfg_array; 1373 int n_cfgs; 1374 int cfg; 1375 1376 if ((dip == NULL) || (dev_data == NULL)) { 1377 1378 return; 1379 } 1380 cfg_array = dev_data->dev_cfg; 1381 n_cfgs = dev_data->dev_n_cfg; 1382 1383 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1384 "usb_free_descr_tree starting for %s%d", 1385 ddi_driver_name(dip), ddi_get_instance(dip)); 1386 1387 for (cfg = 0; cfg < n_cfgs; cfg++) { 1388 if (cfg_array[cfg].cfg_if) { 1389 usba_free_if_array(cfg_array[cfg].cfg_if, 1390 cfg_array[cfg].cfg_n_if); 1391 } 1392 if (cfg_array[cfg].cfg_cvs) { 1393 usba_free_cv_array(cfg_array[cfg].cfg_cvs, 1394 cfg_array[cfg].cfg_n_cvs); 1395 } 1396 if (cfg_array[cfg].cfg_str) { 1397 kmem_free(cfg_array[cfg].cfg_str, 1398 cfg_array[cfg].cfg_strsize); 1399 } 1400 } 1401 1402 if (cfg_array) { 1403 kmem_free(cfg_array, (sizeof (usb_cfg_data_t) * n_cfgs)); 1404 } 1405 1406 dev_data->dev_parse_level = USB_PARSE_LVL_NONE; 1407 dev_data->dev_n_cfg = 0; 1408 dev_data->dev_cfg = NULL; 1409 dev_data->dev_curr_cfg = NULL; 1410 1411 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1412 "usb_free_descr_tree done"); 1413 } 1414 1415 1416 /* 1417 * usba_free_if_array: 1418 * Free a configuration's array of interface nodes and their subtrees of 1419 * interface alternate, endpoint and c/v descriptors. 1420 * 1421 * Arguments: 1422 * if_array - pointer to array of interfaces to remove. 1423 * n_ifs - number of elements in the array to remove. 1424 */ 1425 static void 1426 usba_free_if_array(usb_if_data_t *if_array, uint_t n_ifs) 1427 { 1428 uint_t which_if; 1429 uint_t which_alt; 1430 uint_t n_alts; 1431 usb_alt_if_data_t *altif; 1432 1433 for (which_if = 0; which_if < n_ifs; which_if++) { 1434 n_alts = if_array[which_if].if_n_alt; 1435 1436 /* Every interface has at least one alternate. */ 1437 for (which_alt = 0; which_alt < n_alts; which_alt++) { 1438 altif = &if_array[which_if].if_alt[which_alt]; 1439 usba_free_ep_array(altif->altif_ep, altif->altif_n_ep); 1440 usba_free_cv_array(altif->altif_cvs, 1441 altif->altif_n_cvs); 1442 kmem_free(altif->altif_str, altif->altif_strsize); 1443 } 1444 1445 kmem_free(if_array[which_if].if_alt, 1446 (sizeof (usb_alt_if_data_t) * n_alts)); 1447 } 1448 1449 /* Free the interface array itself. */ 1450 kmem_free(if_array, (sizeof (usb_if_data_t) * n_ifs)); 1451 } 1452 1453 1454 /* 1455 * usba_free_ep_array: 1456 * Free an array of endpoint nodes and their subtrees of c/v descriptors. 1457 * 1458 * Arguments: 1459 * ep_array - pointer to array of endpoints to remove. 1460 * n_eps - number of elements in the array to remove. 1461 */ 1462 static void 1463 usba_free_ep_array(usb_ep_data_t *ep_array, uint_t n_eps) 1464 { 1465 uint_t ep; 1466 1467 for (ep = 0; ep < n_eps; ep++) { 1468 usba_free_cv_array(ep_array[ep].ep_cvs, ep_array[ep].ep_n_cvs); 1469 } 1470 1471 kmem_free(ep_array, (sizeof (usb_ep_data_t) * n_eps)); 1472 } 1473 1474 1475 /* 1476 * usba_free_cv_array: 1477 * Free an array of class/vendor (c/v) descriptor nodes. 1478 * 1479 * Arguments: 1480 * cv_array - pointer to array of c/v nodes to remove. 1481 * n_cvs - number of elements in the array to remove. 1482 */ 1483 static void 1484 usba_free_cv_array(usb_cvs_data_t *cv_array, uint_t n_cvs) 1485 { 1486 uint_t cv_node; 1487 1488 /* Free data areas hanging off of each c/v descriptor. */ 1489 for (cv_node = 0; cv_node < n_cvs; cv_node++) { 1490 kmem_free(cv_array[cv_node].cvs_buf, 1491 cv_array[cv_node].cvs_buf_len); 1492 } 1493 1494 /* Free the array of cv descriptors. */ 1495 kmem_free(cv_array, (sizeof (usb_cvs_data_t) * n_cvs)); 1496 } 1497 1498 1499 /* 1500 * usb_log_descr_tree: 1501 * Log to the usba_debug_buf a descriptor tree as returned by 1502 * usbai_register_client. 1503 * 1504 * Arguments: 1505 * dev_data - pointer to registration area containing the tree 1506 * log_handle - pointer to log handle to use for dumping. 1507 * level - print level, one of USB_LOG_L0 ... USB_LOG_L4 1508 * Please see usb_log(9F) for details. 1509 * mask - print mask. Please see usb_log(9F) for details. 1510 * 1511 * Returns: 1512 * USB_SUCCESS - tree successfully dumped 1513 * USB_INVALID_CONTEXT - called from callback context 1514 * USB_INVALID_ARGS - bad arguments given 1515 */ 1516 int 1517 usb_log_descr_tree(usb_client_dev_data_t *dev_data, 1518 usb_log_handle_t log_handle, uint_t level, uint_t mask) 1519 { 1520 return (usba_dump_descr_tree(NULL, dev_data, log_handle, level, mask)); 1521 } 1522 1523 1524 /* 1525 * usb_print_descr_tree: 1526 * Print to the screen a descriptor tree as returned by 1527 * usbai_register_client. 1528 * 1529 * Arguments: 1530 * dip - pointer to devinfo of the client 1531 * dev_data - pointer to registration area containing the tree 1532 * 1533 * Returns: 1534 * USB_SUCCESS - tree successfully dumped 1535 * USB_INVALID_CONTEXT - called from callback context 1536 * USB_INVALID_ARGS - bad arguments given 1537 */ 1538 int 1539 usb_print_descr_tree(dev_info_t *dip, usb_client_dev_data_t *dev_data) 1540 { 1541 return (usba_dump_descr_tree(dip, dev_data, NULL, 0, 0)); 1542 } 1543 1544 1545 /* 1546 * usba_dump_descr_tree: 1547 * Dump a descriptor tree. 1548 * 1549 * Arguments: 1550 * dip - pointer to devinfo of the client. Used when no 1551 * log_handle argument given. 1552 * usb_reg - pointer to registration area containing the tree 1553 * log_handle - pointer to log handle to use for dumping. If NULL, 1554 * use internal log handle, which dumps to screen. 1555 * level - print level, one of USB_LOG_L0 ... USB_LOG_L4 1556 * Used only when log_handle provided. 1557 * mask - print mask, used when log_handle argument provided. 1558 * 1559 * Returns: 1560 * USB_SUCCESS - tree successfully dumped 1561 * USB_INVALID_CONTEXT - called from callback context 1562 * USB_INVALID_ARGS - bad arguments given 1563 */ 1564 static int 1565 usba_dump_descr_tree(dev_info_t *dip, usb_client_dev_data_t *usb_reg, 1566 usb_log_handle_t log_handle, uint_t level, uint_t mask) 1567 { 1568 usb_log_handle_t dump_handle; 1569 uint_t dump_level; 1570 uint_t dump_mask; 1571 int which_config; /* Counters. */ 1572 int which_if; 1573 int which_cv; 1574 usb_cfg_data_t *config; /* ptr to current configuration tree node */ 1575 usb_cfg_descr_t *config_descr; /* and its USB descriptor. */ 1576 char *string; 1577 char *name_string = NULL; 1578 int name_string_size; 1579 1580 if ((usb_reg == NULL) || ((log_handle == NULL) && (dip == NULL))) { 1581 1582 return (USB_INVALID_ARGS); 1583 } 1584 1585 /* 1586 * To keep calling this simple, kmem_zalloc with the sleep flag always. 1587 * This means no interrupt context is allowed. 1588 */ 1589 if (servicing_interrupt()) { 1590 1591 return (USB_INVALID_CONTEXT); 1592 } 1593 1594 string = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP); 1595 1596 if (log_handle != NULL) { 1597 dump_level = level; 1598 dump_mask = mask; 1599 dump_handle = log_handle; 1600 } else { 1601 dump_level = USB_LOG_L1; 1602 dump_mask = DPRINT_MASK_ALL; 1603 1604 /* Build device name string. */ 1605 (void) snprintf(string, USB_MAXSTRINGLEN, 1606 "Port%d", usb_get_addr(dip)); 1607 name_string_size = strlen(string) + 1; 1608 name_string = kmem_zalloc(name_string_size, KM_SLEEP); 1609 (void) strcpy(name_string, string); 1610 1611 /* Allocate a log handle specifying the name string. */ 1612 dump_handle = usb_alloc_log_hdl(NULL, name_string, 1613 &dump_level, &dump_mask, NULL, 1614 USB_FLAGS_SLEEP); 1615 } 1616 1617 (void) usb_log(dump_handle, dump_level, dump_mask, 1618 "USB descriptor tree for %s %s", 1619 (usb_reg->dev_mfg != NULL ? usb_reg->dev_mfg : ""), 1620 (usb_reg->dev_product != NULL ? usb_reg->dev_product : "")); 1621 if (usb_reg->dev_n_cfg == 0) { 1622 (void) usb_log(dump_handle, dump_level, dump_mask, 1623 "No descriptor tree present"); 1624 } else { 1625 (void) usb_log(dump_handle, dump_level, dump_mask, 1626 "highest configuration found=%d", usb_reg->dev_n_cfg - 1); 1627 } 1628 1629 for (which_config = 0; which_config < usb_reg->dev_n_cfg; 1630 which_config++) { 1631 config = &usb_reg->dev_cfg[which_config]; 1632 config_descr = &config->cfg_descr; 1633 if (config_descr->bLength == 0) { 1634 1635 continue; 1636 } 1637 if (dump_level == USB_LOG_L0) { 1638 (void) usb_log(dump_handle, dump_level, dump_mask, " "); 1639 } 1640 (void) usb_log(dump_handle, dump_level, dump_mask, 1641 "Configuration #%d (Addr= 0x%p)", which_config, 1642 (void *)config); 1643 (void) usb_log(dump_handle, dump_level, dump_mask, 1644 "String descr=%s", config->cfg_str); 1645 (void) usb_log(dump_handle, dump_level, dump_mask, 1646 "config descr: len=%d tp=%d totLen=%d numIf=%d " 1647 "cfgVal=%d att=0x%x pwr=%d", 1648 config_descr->bLength, config_descr->bDescriptorType, 1649 config_descr->wTotalLength, config_descr->bNumInterfaces, 1650 config_descr->bConfigurationValue, 1651 config_descr->bmAttributes, config_descr->bMaxPower); 1652 if ((config->cfg_n_if > 0) || (config->cfg_n_cvs > 0)) { 1653 (void) usb_log(dump_handle, dump_level, dump_mask, 1654 "usb_cfg_data_t shows max if=%d " 1655 "and %d cv descr(s).", 1656 config->cfg_n_if - 1, config->cfg_n_cvs); 1657 } 1658 1659 for (which_if = 0; which_if < config->cfg_n_if; 1660 which_if++) { 1661 1662 if (dump_level == USB_LOG_L0) { 1663 (void) usb_log(dump_handle, dump_level, 1664 dump_mask, " "); 1665 } 1666 (void) usb_log(dump_handle, dump_level, dump_mask, 1667 " interface #%d (0x%p)", 1668 which_if, (void *)&config->cfg_if[which_if]); 1669 usba_dump_if(&config->cfg_if[which_if], 1670 dump_handle, dump_level, dump_mask, string); 1671 } 1672 1673 for (which_cv = 0; which_cv < config->cfg_n_cvs; which_cv++) { 1674 (void) usb_log(dump_handle, dump_level, dump_mask, 1675 " config cv descriptor %d (Address=0x%p)", 1676 which_cv, (void *)&config->cfg_cvs[which_cv]); 1677 usba_dump_cv(&config->cfg_cvs[which_cv], 1678 dump_handle, dump_level, dump_mask, string, 4); 1679 } 1680 } 1681 1682 (void) usb_log(dump_handle, dump_level, dump_mask, 1683 "Returning dev_curr_cfg:0x%p, dev_curr_if:%d", 1684 (void *)usb_reg->dev_curr_cfg, usb_reg->dev_curr_if); 1685 1686 if (log_handle == NULL) { 1687 usb_free_log_hdl(dump_handle); 1688 } 1689 if (name_string != NULL) { 1690 kmem_free(name_string, name_string_size); 1691 } 1692 kmem_free(string, USB_MAXSTRINGLEN); 1693 1694 return (USB_SUCCESS); 1695 } 1696 1697 1698 /* 1699 * usba_dump_if: 1700 * Dump an interface node and its branches. 1701 * 1702 * Arguments: 1703 * which_if - interface node to dump 1704 * dump_handle - write data through this log handle 1705 * dump_level - level passed to usb_log 1706 * dump_mask - mask passed to usb_log 1707 * string - temporary area used for processing 1708 * 1709 */ 1710 static void 1711 usba_dump_if(usb_if_data_t *which_if, usb_log_handle_t dump_handle, 1712 uint_t dump_level, uint_t dump_mask, char *string) 1713 { 1714 int which_alt; /* Number of alt being dumped */ 1715 usb_alt_if_data_t *alt; /* Pointer to it. */ 1716 usb_if_descr_t *if_descr; /* Pointer to its USB descr. */ 1717 int which_ep; /* Endpoint counter. */ 1718 int which_cv; /* C/V descr counter. */ 1719 1720 for (which_alt = 0; which_alt < which_if->if_n_alt; which_alt++) { 1721 alt = &which_if->if_alt[which_alt]; 1722 if_descr = &alt->altif_descr; 1723 1724 if (if_descr->bLength == 0) { 1725 1726 continue; 1727 } 1728 if (dump_level == USB_LOG_L0) { 1729 (void) usb_log(dump_handle, dump_level, dump_mask, " "); 1730 } 1731 (void) usb_log(dump_handle, dump_level, dump_mask, 1732 "\tAlt #%d (0x%p)", which_alt, (void *)alt); 1733 (void) usb_log(dump_handle, dump_level, dump_mask, 1734 "\tString descr=%s", alt->altif_str); 1735 (void) usb_log(dump_handle, dump_level, dump_mask, 1736 "\tif descr: len=%d type=%d if=%d alt=%d n_ept=%d " 1737 "cls=%d sub=%d proto=%d", 1738 if_descr->bLength, 1739 if_descr->bDescriptorType, if_descr->bInterfaceNumber, 1740 if_descr->bAlternateSetting, if_descr->bNumEndpoints, 1741 if_descr->bInterfaceClass, if_descr->bInterfaceSubClass, 1742 if_descr->bInterfaceProtocol); 1743 1744 if ((alt->altif_n_ep > 0) || (alt->altif_n_cvs > 0)) { 1745 (void) usb_log(dump_handle, dump_level, dump_mask, 1746 "\tusb_alt_if_data_t shows max ep=%d " 1747 "and %d cv descr(s).", 1748 alt->altif_n_ep - 1, alt->altif_n_cvs); 1749 } 1750 1751 for (which_ep = 0; which_ep < alt->altif_n_ep; 1752 which_ep++) { 1753 if (alt->altif_ep[which_ep].ep_descr.bLength == 0) { 1754 1755 continue; 1756 } 1757 if (dump_level == USB_LOG_L0) { 1758 (void) usb_log(dump_handle, dump_level, 1759 dump_mask, " "); 1760 } 1761 usba_dump_ep(which_ep, &alt->altif_ep[which_ep], 1762 dump_handle, dump_level, dump_mask, string); 1763 } 1764 1765 for (which_cv = 0; which_cv < alt->altif_n_cvs; which_cv++) { 1766 if (dump_level == USB_LOG_L0) { 1767 (void) usb_log(dump_handle, dump_level, 1768 dump_mask, " "); 1769 } 1770 (void) usb_log(dump_handle, dump_level, dump_mask, 1771 "\talt cv descriptor #%d (0x%p), size=%d", 1772 which_cv, (void *)&alt->altif_cvs[which_cv], 1773 alt->altif_cvs[which_cv].cvs_buf_len); 1774 usba_dump_cv(&alt->altif_cvs[which_cv], 1775 dump_handle, dump_level, dump_mask, string, 2); 1776 } 1777 } 1778 } 1779 1780 1781 /* 1782 * usba_dump_ep: 1783 * Dump an endpoint node and its branches. 1784 * 1785 * Arguments: 1786 * which_ep - index to display 1787 * ep - endpoint node to dump 1788 * dump_handle - write data through this log handle 1789 * dump_level - level passed to usb_log 1790 * dump_mask - mask passed to usb_log 1791 * string - temporary area used for processing 1792 * 1793 */ 1794 static void 1795 usba_dump_ep(uint_t which_ep, usb_ep_data_t *ep, usb_log_handle_t dump_handle, 1796 uint_t dump_level, uint_t dump_mask, char *string) 1797 { 1798 int which_cv; 1799 usb_ep_descr_t *ep_descr = &ep->ep_descr; 1800 1801 (void) usb_log(dump_handle, dump_level, dump_mask, 1802 "\t endpoint[%d], epaddr=0x%x (0x%p)", which_ep, 1803 ep_descr->bEndpointAddress, (void *)ep); 1804 (void) usb_log(dump_handle, dump_level, dump_mask, 1805 "\t len=%d type=%d attr=0x%x pktsize=%d interval=%d", 1806 ep_descr->bLength, ep_descr->bDescriptorType, 1807 ep_descr->bmAttributes, ep_descr->wMaxPacketSize, 1808 ep_descr->bInterval); 1809 if (ep->ep_n_cvs > 0) { 1810 (void) usb_log(dump_handle, dump_level, dump_mask, 1811 "\t usb_ep_data_t shows %d cv descr(s)", ep->ep_n_cvs); 1812 } 1813 1814 for (which_cv = 0; which_cv < ep->ep_n_cvs; which_cv++) { 1815 if (dump_level == USB_LOG_L0) { 1816 (void) usb_log(dump_handle, dump_level, 1817 dump_mask, " "); 1818 } 1819 (void) usb_log(dump_handle, dump_level, dump_mask, 1820 "\t endpoint cv descriptor %d (0x%p), size=%d", 1821 which_cv, (void *)&ep->ep_cvs[which_cv], 1822 ep->ep_cvs[which_cv].cvs_buf_len); 1823 usba_dump_cv(&ep->ep_cvs[which_cv], 1824 dump_handle, dump_level, dump_mask, string, 3); 1825 } 1826 } 1827 1828 1829 /* 1830 * usba_dump_cv: 1831 * Dump a raw class or vendor specific descriptor. 1832 * 1833 * Arguments: 1834 * cv_node - pointer to the descriptor to dump 1835 * dump_handle - write data through this log handle 1836 * dump_level - level passed to usb_log 1837 * dump_mask - mask passed to usb_log 1838 * string - temporary area used for processing 1839 * indent - number of tabs to indent output 1840 * 1841 */ 1842 static void 1843 usba_dump_cv(usb_cvs_data_t *cv_node, usb_log_handle_t dump_handle, 1844 uint_t dump_level, uint_t dump_mask, char *string, int indent) 1845 { 1846 if (cv_node) { 1847 usba_dump_bin(cv_node->cvs_buf, cv_node->cvs_buf_len, indent, 1848 dump_handle, dump_level, dump_mask, string, 1849 USB_MAXSTRINGLEN); 1850 } 1851 } 1852 1853 1854 /* 1855 * usba_dump_bin: 1856 * Generic byte dump function. 1857 * 1858 * Arguments: 1859 * data - pointer to the data to dump 1860 * max_bytes - amount of data to dump 1861 * indent - number of indentation levels 1862 * dump_handle - write data through this log handle 1863 * dump_level - level passed to usb_log 1864 * dump_mask - mask passed to usb_log 1865 * buffer - temporary area used for processing 1866 * bufferlen - size of the temporary string area 1867 * 1868 */ 1869 static void 1870 usba_dump_bin(uint8_t *data, int max_bytes, int indent, 1871 usb_log_handle_t dump_handle, uint_t dump_level, uint_t dump_mask, 1872 char *buffer, int bufferlen) 1873 { 1874 int i; 1875 int bufoffset = 0; 1876 int nexthere; 1877 1878 if ((indent * SPACES_PER_INDENT) > 1879 (bufferlen - (BINDUMP_BYTES_PER_LINE * 3))) { 1880 (void) usb_log(dump_handle, dump_level, dump_mask, 1881 "Offset to usb_dump_bin must be %d or less. " 1882 "Setting to 0.\n", 1883 (bufferlen - (BINDUMP_BYTES_PER_LINE * 3))); 1884 indent = 0; 1885 } 1886 1887 /* Assume a tab is 2 four-space units. */ 1888 for (i = 0; i < indent/2; i++) { 1889 buffer[bufoffset] = '\t'; 1890 bufoffset++; 1891 } 1892 1893 if (indent % 2) { 1894 (void) strcpy(&buffer[bufoffset], INDENT_SPACE_STR); 1895 bufoffset += SPACES_PER_INDENT; 1896 } 1897 1898 i = 0; /* Num dumped bytes put on this line. */ 1899 nexthere = bufoffset; 1900 while (i < max_bytes) { 1901 (void) sprintf(&buffer[nexthere], "%2x ", *data++); 1902 nexthere += 3; 1903 i++; 1904 if (!(i % BINDUMP_BYTES_PER_LINE)) { 1905 buffer[nexthere] = '\0'; 1906 (void) usb_log(dump_handle, dump_level, dump_mask, 1907 buffer); 1908 nexthere = bufoffset; 1909 } 1910 } 1911 1912 if (nexthere > bufoffset) { 1913 buffer[nexthere] = '\0'; 1914 (void) usb_log(dump_handle, dump_level, dump_mask, buffer); 1915 } 1916 } 1917