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