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