1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright 2019 Joyent, Inc. 26 */ 27 28 29 #include <sys/mdb_modapi.h> 30 #include <sys/sysmacros.h> 31 32 #include <sys/usb/usba.h> 33 #include <sys/usb/usba/usba_types.h> 34 #include <sys/usb/clients/hid/hid.h> 35 #include <sys/usb/clients/hidparser/hidparser.h> 36 #include <sys/usb/clients/hidparser/hidparser_impl.h> 37 #include <sys/usb/usba/genconsole.h> 38 #include <sys/usb/clients/hid/hidvar.h> 39 40 41 /* ****************************************************************** */ 42 43 /* extenal definition */ 44 45 typedef struct mdb_ctf_id { 46 void *_opaque[2]; 47 } mdb_ctf_id_t; 48 49 extern int mdb_ctf_lookup_by_name(const char *, mdb_ctf_id_t *); 50 51 extern int mdb_devinfo2driver(uintptr_t, char *, size_t); 52 53 extern int mdb_devinfo2statep(uintptr_t, char *, uintptr_t *); 54 55 extern char *mdb_ddi_pathname(uintptr_t, char *, size_t); 56 57 58 /* ****************************************************************** */ 59 60 /* internal definition */ 61 62 #define OPT_TREE 0x01 63 #define OPT_VERB 0x02 64 65 #define STRLEN 256 66 #define BYTE_OFFSET 8 67 68 69 typedef struct usb_descr_item { 70 uint_t nlen; /* if it's an byte array, nlen += BYTE_OFFSET */ 71 char *name; /* descriptor item name */ 72 } usb_descr_item_t; 73 74 /* define the known descriptor items */ 75 static usb_descr_item_t usb_cfg_descr[] = { 76 {1, "bLength"}, 77 {1, "bDescriptorType"}, 78 {2, "wTotalLength"}, 79 {1, "bNumInterfaces"}, 80 {1, "bConfigurationValue"}, 81 {1, "iConfiguration"}, 82 {1, "bmAttributes"}, 83 {1, "bMaxPower"}, 84 }; 85 static uint_t usb_cfg_item = 8; 86 87 static usb_descr_item_t usb_ia_descr[] = { 88 {1, "bLength"}, 89 {1, "bDescriptorType"}, 90 {1, "bFirstInterface"}, 91 {1, "bInterfaceCount"}, 92 {1, "bFunctionClass"}, 93 {1, "bFunctionSubClass"}, 94 {1, "bFunctionProtocol"}, 95 {1, "iFunction"}, 96 }; 97 static uint_t usb_ia_item = 8; 98 99 static usb_descr_item_t usb_if_descr[] = { 100 {1, "bLength"}, 101 {1, "bDescriptorType"}, 102 {1, "bInterfaceNumber"}, 103 {1, "bAlternateSetting"}, 104 {1, "bNumEndpoints"}, 105 {1, "bInterfaceClass"}, 106 {1, "bInterfaceSubClass"}, 107 {1, "bInterfaceProtocol"}, 108 {1, "iInterface"}, 109 }; 110 static uint_t usb_if_item = 9; 111 112 static usb_descr_item_t usb_ep_descr[] = { 113 {1, "bLength"}, 114 {1, "bDescriptorType"}, 115 {1, "bEndpointAddress"}, 116 {1, "bmAttributes"}, 117 {2, "wMaxPacketSize"}, 118 {1, "bInterval"}, 119 }; 120 static uint_t usb_ep_item = 6; 121 122 static usb_descr_item_t usb_ep_ss_comp_descr[] = { 123 {1, "bLength"}, 124 {1, "bDescriptorType"}, 125 {1, "bMaxBurst"}, 126 {1, "bmAttributes"}, 127 {2, "wBytesPerInterval"} 128 }; 129 static uint_t usb_ep_ss_comp_item = 5; 130 131 static usb_descr_item_t usb_qlf_descr[] = { 132 {1, "bLength"}, 133 {1, "bDescriptorType"}, 134 {2, "bcdUSB"}, 135 {1, "bDeviceClass"}, 136 {1, "bDeviceSubClass"}, 137 {1, "bDeviceProtocol"}, 138 {1, "bMaxPacketSize0"}, 139 {1, "bNumConfigurations"}, 140 {1, "bReserved"}, 141 }; 142 static uint_t usb_qlf_item = 9; 143 144 static usb_descr_item_t usb_str_descr[] = { 145 {1, "bLength"}, 146 {1, "bDescriptorType"}, 147 {1, "bString"}, 148 }; 149 static uint_t usb_str_item = 3; 150 151 static usb_descr_item_t usb_wa_descr[] = { 152 {1, "bLength"}, 153 {1, "bDescriptorType"}, 154 {2, "bcdWAVersion"}, 155 {1, "bNumPorts"}, 156 {1, "bmAttributes"}, 157 {2, "wNumRPipes"}, 158 {2, "wRPipeMaxBlock"}, 159 {1, "bRPipeBlockSize"}, 160 {1, "bPwrOn2PwrGood"}, 161 {1, "bNumMMCIEs"}, 162 {1, "DeviceRemovable"}, 163 }; 164 165 static uint_t usb_wa_item = 11; 166 167 static usb_descr_item_t usb_hid_descr[] = { 168 {1, "bLength"}, 169 {1, "bDescriptorType"}, 170 {2, "bcdHID"}, 171 {1, "bCountryCode"}, 172 {1, "bNumDescriptors"}, 173 {1, "bReportDescriptorType"}, 174 {2, "wReportDescriptorLength"}, 175 }; 176 static uint_t usb_hid_item = 7; 177 178 static usb_descr_item_t usb_ac_header_descr[] = { 179 {1, "bLength"}, 180 {1, "bDescriptorType"}, 181 {1, "bDescriptorSubType"}, 182 {2, "bcdADC"}, 183 {2, "wTotalLength"}, 184 {1, "blnCollection"}, 185 {1, "baInterfaceNr"}, 186 }; 187 static uint_t usb_ac_header_item = 7; 188 189 static usb_descr_item_t usb_ac_input_term_descr[] = { 190 {1, "bLength"}, 191 {1, "bDescriptorType"}, 192 {1, "bDescriptorSubType"}, 193 {1, "bTerminalID"}, 194 {2, "wTerminalType"}, 195 {1, "bAssocTerminal"}, 196 {1, "bNrChannels"}, 197 {2, "wChannelConfig"}, 198 {1, "iChannelNames"}, 199 {1, "iTerminal"}, 200 }; 201 static uint_t usb_ac_input_term_item = 10; 202 203 static usb_descr_item_t usb_ac_output_term_descr[] = { 204 {1, "bLength"}, 205 {1, "bDescriptorType"}, 206 {1, "bDescriptorSubType"}, 207 {1, "bTerminalID"}, 208 {2, "wTerminalType"}, 209 {1, "bAssocTerminal"}, 210 {1, "bSourceID"}, 211 {1, "iTerminal"}, 212 }; 213 static uint_t usb_ac_output_term_item = 8; 214 215 static usb_descr_item_t usb_ac_mixer_descr[] = { 216 {1, "bLength"}, 217 {1, "bDescriptorType"}, 218 {1, "bDescriptorSubType"}, 219 {1, "bUnitID"}, 220 {1, "bNrInPins"}, 221 {1, "baSourceID"}, 222 }; 223 static uint_t usb_ac_mixer_item = 6; 224 225 static usb_descr_item_t usb_ac_selector_descr[] = { 226 {1, "bLength"}, 227 {1, "bDescriptorType"}, 228 {1, "bDescriptorSubType"}, 229 {1, "bUnitID"}, 230 {1, "bNrInPins"}, 231 {1, "baSourceID"}, 232 }; 233 static uint_t usb_ac_selector_item = 6; 234 235 static usb_descr_item_t usb_ac_feature_descr[] = { 236 {1, "bLength"}, 237 {1, "bDescriptorType"}, 238 {1, "bDescriptorSubType"}, 239 {1, "bUnitID"}, 240 {1, "bSourceID"}, 241 {1, "bControlSize"}, 242 {1, "bmaControls"}, 243 }; 244 static uint_t usb_ac_feature_item = 7; 245 246 static usb_descr_item_t usb_ac_processing_descr[] = { 247 {1, "bLength"}, 248 {1, "bDescriptorType"}, 249 {1, "bDescriptorSubType"}, 250 {1, "bUnitID"}, 251 {1, "wProcessType"}, 252 {1, "bNrInPins"}, 253 {1, "baSourceID"}, 254 }; 255 static uint_t usb_ac_processing_item = 7; 256 257 static usb_descr_item_t usb_ac_extension_descr[] = { 258 {1, "bLength"}, 259 {1, "bDescriptorType"}, 260 {1, "bDescriptorSubType"}, 261 {1, "wExtensionCode"}, 262 {1, "bUnitID"}, 263 {1, "bNrInPins"}, 264 {1, "baSourceID"}, 265 }; 266 static uint_t usb_ac_extension_item = 7; 267 268 static usb_descr_item_t usb_as_ep_descr[] = { 269 {1, "blength"}, 270 {1, "bDescriptorType"}, 271 {1, "bDescriptorSubType"}, 272 {1, "bmAttributes"}, 273 {1, "bLockDelayUnits"}, 274 {2, "wLockDelay"}, 275 }; 276 static uint_t usb_as_ep_item = 6; 277 278 static usb_descr_item_t usb_as_if_descr[] = { 279 {1, "blength"}, 280 {1, "bDescriptorType"}, 281 {1, "bDescriptorSubType"}, 282 {1, "bTerminalLink"}, 283 {1, "bDelay"}, 284 {2, "wFormatTag"}, 285 }; 286 static uint_t usb_as_if_item = 6; 287 288 static usb_descr_item_t usb_as_format_descr[] = { 289 {1, "blength"}, 290 {1, "bDescriptorType"}, 291 {1, "bDescriptorSubType"}, 292 {1, "bFormatType"}, 293 {1, "bNrChannels"}, 294 {1, "bSubFrameSize"}, 295 {1, "bBitResolution"}, 296 {1, "bSamFreqType"}, 297 {1, "bSamFreqs"}, 298 }; 299 static uint_t usb_as_format_item = 9; 300 301 static usb_descr_item_t usb_vc_header_descr[] = { 302 {1, "bLength"}, 303 {1, "bDescriptorType"}, 304 {1, "bDescriptorSubtype"}, 305 {2, "bcdUVC"}, 306 {2, "wTotalLength"}, 307 {4, "dwClockFrequency"}, 308 {1, "bInCollection"}, 309 }; 310 static uint_t usb_vc_header_item = 7; 311 312 static usb_descr_item_t usb_vc_input_term_descr[] = { 313 {1, "bLength"}, 314 {1, "bDescriptorType"}, 315 {1, "bDescriptorSubType"}, 316 {1, "bTerminalID"}, 317 {2, "wTerminalType"}, 318 {1, "AssocTerminal"}, 319 {1, "iTerminal"}, 320 }; 321 static uint_t usb_vc_input_term_item = 7; 322 323 static usb_descr_item_t usb_vc_output_term_descr[] = { 324 {1, "bLength"}, 325 {1, "bDescriptorType"}, 326 {1, "bDescriptorSubType"}, 327 {1, "bTerminalID"}, 328 {2, "wTerminalType"}, 329 {1, "AssocTerminal"}, 330 {1, "bSourceID"}, 331 {1, "iTerminal"}, 332 }; 333 static uint_t usb_vc_output_term_item = 8; 334 335 static usb_descr_item_t usb_vc_processing_descr[] = { 336 {1, "bLength"}, 337 {1, "bDescriptorType"}, 338 {1, "bDescriptorSubType"}, 339 {1, "bUnitID"}, 340 {1, "bSourceID"}, 341 {2, "wMaxMultiplier"}, 342 {1, "bControlSize"}, 343 {1, "bmControls"}, 344 }; 345 static uint_t usb_vc_processing_item = 8; 346 347 static usb_descr_item_t usb_vc_selector_descr[] = { 348 {1, "bLength"}, 349 {1, "bDescriptorType"}, 350 {1, "bDescriptorSubType"}, 351 {1, "bUnitID"}, 352 {1, "bNrInPins"}, 353 }; 354 static uint_t usb_vc_selector_item = 5; 355 356 static usb_descr_item_t usb_vc_extension_descr[] = { 357 {1, "bLength"}, 358 {1, "bDescriptorType"}, 359 {1, "bDescriptorSubType"}, 360 {1, "bUnitID"}, 361 {16 + BYTE_OFFSET, "guidExtensionCode[16]"}, 362 {1, "bNumControls"}, 363 {1, "bNrInPins"}, 364 }; 365 static uint_t usb_vc_extension_item = 7; 366 367 static usb_descr_item_t usb_vs_input_header_descr[] = { 368 {1, "bLength"}, 369 {1, "bDescriptorType"}, 370 {1, "bDescriptorSubType"}, 371 {1, "bNumFormats"}, 372 {2, "wTotalLength"}, 373 {1, "bEndpointAddress"}, 374 {1, "bmInfo"}, 375 {1, "bTerminalLink"}, 376 {1, "bStillCaptureMethod"}, 377 {1, "bTriggerSupport"}, 378 {1, "bTriggerUsage"}, 379 {1, "bControlSize"}, 380 {1, "bmaControls"}, 381 }; 382 static uint_t usb_vs_input_header_item = 13; 383 384 static usb_descr_item_t usb_vs_output_header_descr[] = { 385 {1, "bLength"}, 386 {1, "bDescriptorType"}, 387 {1, "bDescriptorSubType"}, 388 {1, "bNumFormats"}, 389 {2, "wTotalLength"}, 390 {1, "bEndpointAddress"}, 391 {1, "bTerminalLink"}, 392 {1, "bControlSize"}, 393 {1, "bmaControls"}, 394 }; 395 static uint_t usb_vs_output_header_item = 9; 396 397 static usb_descr_item_t usb_vs_still_image_descr[] = { 398 {1, "bLength"}, 399 {1, "bDescriptorType"}, 400 {1, "bDescriptorSubType"}, 401 {1, "bEndpointAddress"}, 402 {1, "bNumImageSizePatterns"}, 403 {2, "wWidth"}, 404 {2, "wHeight"}, 405 }; 406 static uint_t usb_vs_still_image_item = 7; 407 408 static usb_descr_item_t usb_vs_color_matching_descr[] = { 409 {1, "bLength"}, 410 {1, "bDescriptorType"}, 411 {1, "bDescriptorSubtype"}, 412 {1, "bColorPrimaries"}, 413 {1, "bTransferCharacteristics"}, 414 {1, "bMatrixCoefficients"}, 415 }; 416 static uint_t usb_vs_color_matching_item = 6; 417 418 static usb_descr_item_t usb_vs_2frame_descr[] = { 419 {1, "bLength"}, 420 {1, "bDescriptorType"}, 421 {1, "bDescriptorSubType"}, 422 {1, "bFrameIndex"}, 423 {1, "bmCapabilities"}, 424 {2, "wWidth"}, 425 {2, "wHeight"}, 426 {4, "dwMinBitRate"}, 427 {4, "dwMaxBitRate"}, 428 {4, "dwMaxVideoFrameBufferSize"}, 429 {4, "dwDefaultFrameInterval"}, 430 {1, "bFrameIntervalType"}, 431 }; 432 static uint_t usb_vs_2frame_item = 12; 433 434 static usb_descr_item_t usb_vs_format_mjpeg_descr[] = { 435 {1, "bLength"}, 436 {1, "bDescriptorType"}, 437 {1, "bDescriptorSubType"}, 438 {1, "bFormatIndex"}, 439 {1, "bNumFrameDescriptors"}, 440 {1, "bmFlags"}, 441 {1, "bDefaultFrameIndex"}, 442 {1, "bAspectRatioX"}, 443 {1, "bAspectRatioY"}, 444 {1, "bmInterlaceFlags"}, 445 {1, "bCopyProtect"}, 446 }; 447 static uint_t usb_vs_format_mjpeg_item = 11; 448 449 static usb_descr_item_t usb_vs_format_uncps_descr[] = { 450 {1, "bLength"}, 451 {1, "bDescriptorType"}, 452 {1, "bDescriptorSubType"}, 453 {1, "bFormatIndex"}, 454 {1, "bNumFrameDescriptors"}, 455 {16 + BYTE_OFFSET, "guidFormat[16]"}, 456 {1, "bBitsPerPixel"}, 457 {1, "bDefaultFrameIndex"}, 458 {1, "bAspectRatioX"}, 459 {1, "bAspectRatioY"}, 460 {1, "bmInterlaceFlags"}, 461 {1, "bCopyProtect"}, 462 }; 463 static uint_t usb_vs_format_uncps_item = 12; 464 465 static usb_descr_item_t usb_vs_format_mp2ts_descr[] = { 466 {1, "bLength"}, 467 {1, "bDescriptorType"}, 468 {1, "bDescriptorSubType"}, 469 {1, "bFormatIndex"}, 470 {1, "bDataOffset"}, 471 {1, "bPacketLength"}, 472 {1, "bStrideLength"}, 473 {16 + BYTE_OFFSET, "guidStrideFormat[16]"}, 474 }; 475 static uint_t usb_vs_format_mp2ts_item = 8; 476 477 static usb_descr_item_t usb_vs_format_dv_descr[] = { 478 {1, "bLength"}, 479 {1, "bDescriptorType"}, 480 {1, "bDescriptorSubType"}, 481 {1, "bFormatIndex"}, 482 {4, "dwMaxVideoFrameBufferSize"}, 483 {1, "bFormatType"}, 484 }; 485 static uint_t usb_vs_format_dv_item = 6; 486 487 static usb_descr_item_t usb_ccid_descr[] = { 488 {1, "bLength"}, 489 {1, "bDescriptorType"}, 490 {2, "bcdCCID"}, 491 {1, "bMaxSlotIndex"}, 492 {1, "bVoltageSupport"}, 493 {4, "dwProtocols"}, 494 {4, "dwDefaultClock"}, 495 {4, "dwMaximumClock"}, 496 {1, "bNumClockSupported"}, 497 {4, "dwDataRate"}, 498 {4, "dwMaxDataRate"}, 499 {1, "bNumDataRatesSupported"}, 500 {4, "dwMaxIFSD"}, 501 {4, "dwSyncProtocols"}, 502 {4, "dwMechanical"}, 503 {4, "dwFeatures"}, 504 {4, "dwMaxCCIDMessageLength"}, 505 {1, "bClassGetResponse"}, 506 {1, "bClassEnvelope"}, 507 {2, "wLcdLayout"}, 508 {1, "bPinSupport"}, 509 {1, "bMaxCCIDBusySlots"} 510 }; 511 static uint_t usb_ccid_item = ARRAY_SIZE(usb_ccid_descr); 512 513 514 /* ****************************************************************** */ 515 516 typedef struct hci_state { 517 void *hci_dip; 518 uint_t hci_instance; 519 void *hci_hcdi_ops; 520 uint_t hci_flags; 521 uint16_t vendor_id; 522 uint16_t device_id; 523 } hci_state_t; 524 525 static int prt_usb_tree(uintptr_t paddr, uint_t flag); 526 527 static int prt_usb_tree_node(uintptr_t paddr); 528 529 static void prt_usb_hid_item(uintptr_t paddr); 530 531 static void prt_usb_hid_item_params(entity_item_t *item); 532 533 static void prt_usb_hid_item_attrs(uintptr_t paddr); 534 535 static void prt_usb_hid_item_tags(uint_t tag); 536 537 static void prt_usb_hid_item_data(uintptr_t paddr, uint_t len); 538 539 static int prt_usb_desc(uintptr_t usb_cfg, uint_t cfg_len); 540 541 static int prt_usb_ac_desc(uintptr_t paddr, uint_t nlen); 542 543 static int prt_usb_as_desc(uintptr_t paddr, uint_t nlen); 544 545 static int prt_usb_vc_desc(uintptr_t paddr, uint_t nlen); 546 547 static int prt_usb_vs_desc(uintptr_t paddr, uint_t nlen); 548 549 static int print_descr(uintptr_t, uint_t, usb_descr_item_t *, uint_t); 550 551 static int print_struct(uintptr_t, uint_t, mdb_arg_t *); 552 553 static int prt_usb_buf(uintptr_t, uint_t); 554 555 556 /* ****************************************************************** */ 557 558 /* exported functions */ 559 560 void prt_usb_usage(void); 561 562 int prtusb(uintptr_t, uint_t, int, const mdb_arg_t *); 563 564 /* ****************************************************************** */ 565 566 /* help of prtusb */ 567 void 568 prt_usb_usage(void) 569 { 570 mdb_printf("%-8s : %s\n", "-v", "print all descriptors"); 571 mdb_printf("%-8s : %s\n", "-t", "print device trees"); 572 mdb_printf("%-8s : %s\n", "-i index", "print the device by index"); 573 } 574 575 /* the entry of ::prtusb */ 576 int 577 prtusb(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 578 { 579 static int count = 1; 580 uint64_t sel_num = 0; 581 uint_t usb_flag = 0; 582 usba_device_t usb_dev; 583 usb_dev_descr_t dev_desc; 584 struct dev_info usb_dip; 585 char strbuf[STRLEN]; 586 587 /* print all usba devices if no address assigned */ 588 if (!(flags & DCMD_ADDRSPEC)) { 589 if (mdb_walk_dcmd("usba_device", "prtusb", argc, argv) == -1) { 590 mdb_warn("failed to walk usba_device"); 591 592 return (DCMD_ERR); 593 } 594 595 return (DCMD_OK); 596 } 597 598 /* for the first device, print head */ 599 if (DCMD_HDRSPEC(flags)) { 600 count = 1; 601 mdb_printf("%<u>%-8s%-12s%-6s%-14s%-5s%-12s%-20s%</u>\n", 602 "INDEX", "DRIVER", "INST", "NODE", "GEN", "VID.PID", 603 "PRODUCT"); 604 } 605 606 if (mdb_getopts(argc, argv, 607 'i', MDB_OPT_UINT64, &sel_num, 608 't', MDB_OPT_SETBITS, OPT_TREE, &usb_flag, 609 'v', MDB_OPT_SETBITS, OPT_VERB, &usb_flag, NULL) != argc) { 610 611 return (DCMD_USAGE); 612 } 613 614 if (mdb_vread(&usb_dev, sizeof (usba_device_t), addr) == -1) { 615 mdb_warn("Failed to read usba_device!\n"); 616 617 return (DCMD_ERR); 618 } 619 620 if (mdb_vread(&usb_dip, sizeof (struct dev_info), 621 (uintptr_t)usb_dev.usb_dip) == -1) { 622 mdb_warn("Failed to read dev_info!\n"); 623 624 return (DCMD_ERR); 625 } 626 627 /* process the "-i" */ 628 if (sel_num && sel_num != count) { 629 count++; 630 631 return (DCMD_OK); 632 } 633 634 /* index number of device node */ 635 mdb_printf("%-8x", count++); 636 637 /* driver and instance */ 638 mdb_devinfo2driver((uintptr_t)usb_dev.usb_dip, strbuf, STRLEN); 639 mdb_printf("%-12s%-6d", strbuf, usb_dip.devi_instance); 640 641 /* node name */ 642 if (mdb_readstr(strbuf, STRLEN, 643 (uintptr_t)usb_dip.devi_node_name) != -1) { 644 645 mdb_printf("%-14s", strbuf); 646 } else { 647 648 mdb_printf("%-14s", "No Node Name"); 649 } 650 651 652 if (mdb_vread(&dev_desc, sizeof (usb_dev_descr_t), 653 (uintptr_t)usb_dev.usb_dev_descr) != -1) { 654 655 /* gen (note we read this from the bcd) */ 656 mdb_printf("%01x.%01x ", dev_desc.bcdUSB >> 8, 657 (dev_desc.bcdUSB & 0xf0) >> 4); 658 659 /* vid.pid */ 660 mdb_printf("%04x.%04x ", 661 dev_desc.idVendor, dev_desc.idProduct); 662 } 663 664 /* product string */ 665 if (mdb_readstr(strbuf, STRLEN, 666 (uintptr_t)usb_dev.usb_product_str) != -1) { 667 668 mdb_printf("%s\n", strbuf); 669 } else { 670 671 mdb_printf("%s\n", "No Product String"); 672 } 673 674 /* tree, print usb device tree info */ 675 if (usb_flag & OPT_TREE) { 676 677 mdb_printf("\nusba_device: 0x%lx\n", addr); 678 679 mdb_printf("mfg_prod_sn: "); 680 if (mdb_readstr(strbuf, STRLEN, 681 (uintptr_t)usb_dev.usb_mfg_str) != -1) { 682 mdb_printf("%s - ", strbuf); 683 } else { 684 mdb_printf("NULL - "); 685 } 686 if (mdb_readstr(strbuf, STRLEN, 687 (uintptr_t)usb_dev.usb_product_str) != -1) { 688 mdb_printf("%s - ", strbuf); 689 } else { 690 mdb_printf("NULL -"); 691 } 692 if (mdb_readstr(strbuf, STRLEN, 693 (uintptr_t)usb_dev.usb_serialno_str) != -1) { 694 mdb_printf("%s", strbuf); 695 } else { 696 mdb_printf("NULL"); 697 } 698 699 mdb_printf("\n\n"); 700 prt_usb_tree((uintptr_t)usb_dev.usb_dip, 0); 701 } 702 703 /* verbose, print all descriptors */ 704 if (usb_flag & OPT_VERB) { 705 int i; 706 uintptr_t cfg_buf; 707 uint16_t cfg_len; 708 709 mdb_printf("\n"); 710 711 /* device descriptor */ 712 prt_usb_desc((uintptr_t)usb_dev.usb_dev_descr, 18); 713 714 /* config cloud descriptors */ 715 if (usb_dev.usb_n_cfgs == 1) { 716 mdb_inc_indent(4); 717 mdb_printf("-- Active Config Index 0\n"); 718 mdb_dec_indent(4); 719 prt_usb_desc((uintptr_t)usb_dev.usb_cfg, 720 usb_dev.usb_cfg_length); 721 } else { 722 /* multiple configs */ 723 for (i = 0; i < usb_dev.usb_n_cfgs; i++) { 724 725 if ((mdb_vread(&cfg_len, sizeof (uint16_t), 726 (uintptr_t)(usb_dev.usb_cfg_array_len + i)) 727 != -1) && 728 (mdb_vread(&cfg_buf, sizeof (uintptr_t), 729 (uintptr_t)(usb_dev.usb_cfg_array + i)) 730 != -1)) { 731 mdb_inc_indent(4); 732 if (cfg_buf == 733 (uintptr_t)usb_dev.usb_cfg) { 734 mdb_printf("-- Active Config" 735 " Index %x\n", i); 736 } else { 737 mdb_printf("-- Inactive Config" 738 " Index %x\n", i); 739 } 740 mdb_dec_indent(4); 741 742 prt_usb_desc(cfg_buf, cfg_len); 743 } 744 } 745 } 746 } 747 748 if (usb_flag) { 749 750 mdb_printf("%<u>%-72s%</u>\n", " "); 751 } 752 753 return (DCMD_OK); 754 } 755 756 /* print the info required by "-t" */ 757 static int 758 prt_usb_tree(uintptr_t paddr, uint_t flag) 759 { 760 struct dev_info usb_dip; 761 762 if (mdb_vread(&usb_dip, sizeof (struct dev_info), paddr) == -1) { 763 mdb_warn("prt_usb_tree: Failed to read dev_info!\n"); 764 765 return (DCMD_ERR); 766 } 767 768 prt_usb_tree_node(paddr); 769 770 if (usb_dip.devi_child) { 771 772 mdb_printf("{\n"); 773 mdb_inc_indent(4); 774 prt_usb_tree((uintptr_t)usb_dip.devi_child, 1); 775 mdb_dec_indent(4); 776 mdb_printf("}\n\n"); 777 } 778 779 if (usb_dip.devi_sibling && flag == 1) { 780 /* print the sibling if flag == 1 */ 781 782 prt_usb_tree((uintptr_t)usb_dip.devi_sibling, 1); 783 } 784 785 return (DCMD_OK); 786 } 787 788 static int 789 prt_usb_tree_node(uintptr_t paddr) 790 { 791 struct dev_info usb_dip; 792 uintptr_t statep; 793 uint_t errlevel; 794 char driver_name[STRLEN] = ""; 795 char strbuf[STRLEN] = ""; 796 797 if (mdb_vread(&usb_dip, sizeof (struct dev_info), paddr) == -1) { 798 mdb_warn("prt_usb_tree_node: Failed to read dev_info!\n"); 799 800 return (DCMD_ERR); 801 } 802 803 /* node name */ 804 if (mdb_readstr(strbuf, STRLEN, 805 (uintptr_t)usb_dip.devi_node_name) != -1) { 806 mdb_printf("%s, ", strbuf); 807 } else { 808 mdb_printf("%s, ", "node_name"); 809 } 810 811 /* instance */ 812 mdb_printf("instance #%d ", usb_dip.devi_instance); 813 814 /* driver name */ 815 if (DDI_CF2(&usb_dip)) { 816 817 mdb_devinfo2driver(paddr, driver_name, STRLEN); 818 mdb_printf("(driver name: %s)\n", driver_name); 819 } else { 820 821 mdb_printf("(driver not attached)\n"); 822 } 823 824 /* device path */ 825 mdb_ddi_pathname(paddr, strbuf, STRLEN); 826 mdb_printf(" %s\n", strbuf); 827 828 /* dip addr */ 829 mdb_printf(" dip: 0x%lx\n", paddr); 830 831 /* softe_sate */ 832 mdb_snprintf(strbuf, STRLEN, "%s_statep", driver_name); 833 if (mdb_devinfo2statep(paddr, strbuf, &statep) != -1) { 834 mdb_printf(" %s: 0x%lx\n", strbuf, statep); 835 } 836 837 /* error level */ 838 mdb_snprintf(strbuf, STRLEN, "%s_errlevel", driver_name); 839 if (mdb_readvar(&errlevel, strbuf) != -1) { 840 mdb_printf(" %s: 0x%x\n", strbuf, errlevel); 841 } 842 843 if (strcmp(driver_name, "ehci") == 0) { 844 mdb_arg_t argv[] = { 845 {MDB_TYPE_STRING, {"ehci_state_t"}}, 846 {MDB_TYPE_STRING, {"ehci_root_hub.rh_descr"}} 847 }; 848 mdb_call_dcmd("print", statep, DCMD_ADDRSPEC, 2, argv); 849 } 850 851 if (strcmp(driver_name, "ohci") == 0) { 852 mdb_arg_t argv[] = { 853 {MDB_TYPE_STRING, {"ohci_state_t"}}, 854 {MDB_TYPE_STRING, {"ohci_root_hub.rh_descr"}} 855 }; 856 mdb_call_dcmd("print", statep, DCMD_ADDRSPEC, 2, argv); 857 } 858 859 if (strcmp(driver_name, "uhci") == 0) { 860 mdb_arg_t argv[] = { 861 {MDB_TYPE_STRING, {"uhci_state_t"}}, 862 {MDB_TYPE_STRING, {"uhci_root_hub.rh_descr"}} 863 }; 864 mdb_call_dcmd("print", statep, DCMD_ADDRSPEC, 2, argv); 865 } 866 867 if (strcmp(driver_name, "hubd") == 0) { 868 mdb_arg_t argv[] = { 869 {MDB_TYPE_STRING, {"hubd_t"}}, 870 {MDB_TYPE_STRING, {"h_ep1_xdescr.uex_ep"}} 871 }; 872 mdb_call_dcmd("print", statep, DCMD_ADDRSPEC, 2, argv); 873 } 874 875 if (strcmp(driver_name, "hid") == 0) { 876 hid_state_t hidp; 877 878 if (mdb_vread(&hidp, sizeof (hid_state_t), statep) != -1) { 879 hidparser_handle hid_report; 880 881 if (mdb_vread(&hid_report, sizeof (hidparser_handle), 882 (uintptr_t)hidp.hid_report_descr) != -1) { 883 884 mdb_inc_indent(2); 885 886 mdb_printf("\n"); 887 prt_usb_hid_item((uintptr_t) 888 hid_report.hidparser_handle_parse_tree); 889 890 mdb_dec_indent(2); 891 } 892 } 893 } 894 895 mdb_printf("\n"); 896 897 return (DCMD_OK); 898 } 899 900 /* print hid report descriptor */ 901 static void 902 prt_usb_hid_item(uintptr_t paddr) 903 { 904 entity_item_t item; 905 if (mdb_vread(&item, sizeof (entity_item_t), paddr) != -1) { 906 907 prt_usb_hid_item_attrs((uintptr_t)item.entity_item_attributes); 908 prt_usb_hid_item_params(&item); 909 910 if (item.info.child) { 911 mdb_inc_indent(4); 912 prt_usb_hid_item((uintptr_t)item.info.child); 913 mdb_dec_indent(4); 914 } 915 916 if (item.entity_item_right_sibling) { 917 prt_usb_hid_item((uintptr_t) 918 item.entity_item_right_sibling); 919 } 920 } 921 } 922 923 static void 924 prt_usb_hid_item_params(entity_item_t *item) 925 { 926 switch (item->entity_item_type) { 927 case 0x80: 928 mdb_printf("INPUT "); 929 930 break; 931 case 0x90: 932 mdb_printf("OUTPUT "); 933 934 break; 935 case 0xA0: 936 mdb_printf("COLLECTION "); 937 938 break; 939 case 0xB0: 940 mdb_printf("FEATURE "); 941 942 break; 943 case 0xC0: 944 mdb_printf("END_COLLECTION "); 945 946 break; 947 default: 948 mdb_printf("MAIN_ITEM "); 949 950 break; 951 } 952 953 prt_usb_hid_item_data((uintptr_t)item->entity_item_params, 954 item->entity_item_params_leng); 955 956 mdb_printf("\n"); 957 } 958 959 static void 960 prt_usb_hid_item_attrs(uintptr_t paddr) 961 { 962 entity_attribute_t attr; 963 964 if (mdb_vread(&attr, sizeof (entity_attribute_t), paddr) != -1) { 965 966 prt_usb_hid_item_tags(attr.entity_attribute_tag); 967 prt_usb_hid_item_data((uintptr_t)attr.entity_attribute_value, 968 attr.entity_attribute_length); 969 970 mdb_printf("\n"); 971 972 if (attr.entity_attribute_next) { 973 prt_usb_hid_item_attrs((uintptr_t) 974 attr.entity_attribute_next); 975 } 976 } 977 } 978 979 static void 980 prt_usb_hid_item_data(uintptr_t paddr, uint_t len) 981 { 982 char data[4]; 983 int i; 984 985 if (len > 4) { 986 mdb_warn("Incorrect entity_item_length: 0x%x\n", len); 987 988 return; 989 } 990 991 if (mdb_vread(data, len, paddr) != -1) { 992 993 mdb_printf("( "); 994 for (i = 0; i < len; i++) { 995 mdb_printf("0x%02x ", data[i] & 0xff); 996 } 997 mdb_printf(")"); 998 } 999 } 1000 1001 static void 1002 prt_usb_hid_item_tags(uint_t tag) 1003 { 1004 switch (tag) { 1005 case 0x04: 1006 mdb_printf("usage page "); 1007 1008 break; 1009 case 0x14: 1010 mdb_printf("logical minimum "); 1011 1012 break; 1013 case 0x24: 1014 mdb_printf("logical maximum "); 1015 1016 break; 1017 case 0x34: 1018 mdb_printf("physical minimum "); 1019 1020 break; 1021 case 0x44: 1022 mdb_printf("physical maximum "); 1023 1024 break; 1025 case 0x54: 1026 mdb_printf("exponent "); 1027 1028 break; 1029 case 0x64: 1030 mdb_printf("unit "); 1031 1032 break; 1033 case 0x74: 1034 mdb_printf("report size "); 1035 1036 break; 1037 case 0x84: 1038 mdb_printf("report id "); 1039 1040 break; 1041 case 0x94: 1042 mdb_printf("report count "); 1043 1044 break; 1045 case 0x08: 1046 mdb_printf("usage "); 1047 1048 break; 1049 case 0x18: 1050 mdb_printf("usage min "); 1051 1052 break; 1053 case 0x28: 1054 mdb_printf("usage max "); 1055 1056 break; 1057 1058 default: 1059 mdb_printf("tag "); 1060 } 1061 } 1062 1063 /* print the info required by "-v" */ 1064 static int 1065 prt_usb_desc(uintptr_t usb_cfg, uint_t cfg_len) 1066 { 1067 uintptr_t paddr = usb_cfg; 1068 uintptr_t pend = usb_cfg + cfg_len; 1069 uchar_t desc_type, nlen; 1070 usb_if_descr_t usb_if; 1071 ulong_t indent = 0; 1072 1073 mdb_arg_t argv = {MDB_TYPE_STRING, {"usb_dev_descr_t"}}; 1074 1075 if (mdb_vread(&nlen, 1, paddr) == -1) { 1076 1077 return (DCMD_ERR); 1078 } 1079 while ((paddr + nlen <= pend) && (nlen > 0)) { 1080 if (mdb_vread(&desc_type, 1, paddr + 1) == -1) { 1081 1082 return (DCMD_ERR); 1083 } 1084 1085 switch (desc_type) { 1086 case USB_DESCR_TYPE_DEV: 1087 mdb_printf("Device Descriptor\n"); 1088 print_struct(paddr, nlen, &argv); 1089 1090 break; 1091 case USB_DESCR_TYPE_CFG: 1092 indent = 4; 1093 mdb_inc_indent(indent); 1094 mdb_printf("Configuration Descriptor\n"); 1095 print_descr(paddr, nlen, usb_cfg_descr, usb_cfg_item); 1096 mdb_dec_indent(indent); 1097 1098 break; 1099 case USB_DESCR_TYPE_STRING: 1100 mdb_printf("String Descriptor\n"); 1101 print_descr(paddr, nlen, usb_str_descr, usb_str_item); 1102 1103 break; 1104 case USB_DESCR_TYPE_IF: 1105 indent = 8; 1106 mdb_inc_indent(indent); 1107 mdb_printf("Interface Descriptor\n"); 1108 print_descr(paddr, nlen, usb_if_descr, usb_if_item); 1109 mdb_dec_indent(indent); 1110 mdb_vread(&usb_if, sizeof (usb_if_descr_t), paddr); 1111 1112 break; 1113 case USB_DESCR_TYPE_EP: 1114 indent = 8; 1115 mdb_inc_indent(indent); 1116 mdb_printf("Endpoint Descriptor\n"); 1117 print_descr(paddr, nlen, usb_ep_descr, usb_ep_item); 1118 mdb_dec_indent(indent); 1119 1120 break; 1121 case USB_DESCR_TYPE_SS_EP_COMP: 1122 indent = 12; 1123 mdb_inc_indent(indent); 1124 mdb_printf("SuperSpeed Endpoint Companion " 1125 "Descriptor\n"); 1126 print_descr(paddr, nlen, usb_ep_ss_comp_descr, 1127 usb_ep_ss_comp_item); 1128 mdb_dec_indent(indent); 1129 1130 break; 1131 case USB_DESCR_TYPE_DEV_QLF: 1132 mdb_printf("Device_Qualifier Descriptor\n"); 1133 print_descr(paddr, nlen, usb_qlf_descr, usb_qlf_item); 1134 1135 break; 1136 case USB_DESCR_TYPE_OTHER_SPEED_CFG: 1137 indent = 4; 1138 mdb_inc_indent(indent); 1139 mdb_printf("Other_Speed_Configuration Descriptor\n"); 1140 print_descr(paddr, nlen, usb_cfg_descr, usb_cfg_item); 1141 mdb_dec_indent(indent); 1142 1143 break; 1144 case USB_DESCR_TYPE_IA: 1145 indent = 6; 1146 mdb_inc_indent(indent); 1147 mdb_printf("Interface_Association Descriptor\n"); 1148 print_descr(paddr, nlen, usb_ia_descr, usb_ia_item); 1149 mdb_dec_indent(indent); 1150 1151 break; 1152 case 0x21: /* hid descriptor */ 1153 indent = 12; 1154 mdb_inc_indent(indent); 1155 if (usb_if.bInterfaceClass == 0xe0 && 1156 usb_if.bInterfaceSubClass == 0x02) { 1157 mdb_printf("WA Descriptor\n"); 1158 print_descr(paddr, nlen, usb_wa_descr, 1159 usb_wa_item); 1160 } else if (usb_if.bInterfaceClass == USB_CLASS_CCID && 1161 usb_if.bInterfaceSubClass == 0x0) { 1162 mdb_printf("CCID Descriptor\n"); 1163 print_descr(paddr, nlen, usb_ccid_descr, 1164 usb_ccid_item); 1165 } else { 1166 mdb_printf("HID Descriptor\n"); 1167 print_descr(paddr, nlen, usb_hid_descr, 1168 usb_hid_item); 1169 } 1170 mdb_dec_indent(indent); 1171 1172 break; 1173 case 0x24: /* class specific interfce descriptor */ 1174 indent = 12; 1175 mdb_inc_indent(indent); 1176 if (usb_if.bInterfaceClass == 1 && 1177 usb_if.bInterfaceSubClass == 1) { 1178 mdb_printf("AudioControl_Interface: "); 1179 prt_usb_ac_desc(paddr, nlen); 1180 1181 } else if (usb_if.bInterfaceClass == 1 && 1182 usb_if.bInterfaceSubClass == 2) { 1183 mdb_printf("AudioStream_Interface: "); 1184 prt_usb_as_desc(paddr, nlen); 1185 1186 } else if (usb_if.bInterfaceClass == 0x0E && 1187 usb_if.bInterfaceSubClass == 1) { 1188 mdb_printf("VideoControl_Interface: "); 1189 prt_usb_vc_desc(paddr, nlen); 1190 1191 1192 } else if (usb_if.bInterfaceClass == 0x0E && 1193 usb_if.bInterfaceSubClass == 2) { 1194 mdb_printf("VideoStream_Interface: "); 1195 prt_usb_vs_desc(paddr, nlen); 1196 1197 } else { 1198 mdb_printf("Unknown_Interface:" 1199 "0x%x\n", desc_type); 1200 prt_usb_buf(paddr, nlen); 1201 } 1202 mdb_dec_indent(indent); 1203 1204 break; 1205 case 0x25: /* class specific endpoint descriptor */ 1206 indent = 12; 1207 mdb_inc_indent(indent); 1208 if (usb_if.bInterfaceClass == 0x01) { 1209 mdb_printf("AudioEndpoint:\n"); 1210 print_descr(paddr, nlen, 1211 usb_as_ep_descr, usb_as_ep_item); 1212 1213 } else if (usb_if.bInterfaceClass == 0x0E) { 1214 mdb_printf("VideoEndpoint:\n"); 1215 print_descr(paddr, nlen, 1216 usb_ep_descr, usb_ep_item); 1217 1218 } else { 1219 mdb_printf("Unknown_Endpoint:" 1220 "0x%x\n", desc_type); 1221 prt_usb_buf(paddr, nlen); 1222 } 1223 mdb_dec_indent(indent); 1224 1225 break; 1226 default: 1227 mdb_inc_indent(indent); 1228 mdb_printf("Unknown Descriptor: 0x%x\n", desc_type); 1229 prt_usb_buf(paddr, nlen); 1230 mdb_dec_indent(indent); 1231 1232 break; 1233 } 1234 1235 paddr += nlen; 1236 if (mdb_vread(&nlen, 1, paddr) == -1) { 1237 1238 return (DCMD_ERR); 1239 } 1240 }; 1241 1242 return (DCMD_OK); 1243 } 1244 1245 1246 /* print audio class specific control descriptor */ 1247 static int 1248 prt_usb_ac_desc(uintptr_t addr, uint_t nlen) 1249 { 1250 uchar_t sub_type; 1251 1252 if (mdb_vread(&sub_type, 1, addr + 2) == -1) { 1253 1254 return (DCMD_ERR); 1255 } 1256 switch (sub_type) { 1257 case 0x01: 1258 mdb_printf("header Descriptor\n"); 1259 print_descr(addr, nlen, 1260 usb_ac_header_descr, usb_ac_header_item); 1261 1262 break; 1263 case 0x02: 1264 mdb_printf("input_terminal Descriptor\n"); 1265 print_descr(addr, nlen, 1266 usb_ac_input_term_descr, usb_ac_input_term_item); 1267 1268 break; 1269 case 0x03: 1270 mdb_printf("output_terminal Descriptor\n"); 1271 print_descr(addr, nlen, 1272 usb_ac_output_term_descr, usb_ac_output_term_item); 1273 1274 break; 1275 case 0x04: 1276 mdb_printf("mixer_unit Descriptor\n"); 1277 print_descr(addr, nlen, 1278 usb_ac_mixer_descr, usb_ac_mixer_item); 1279 1280 break; 1281 case 0x05: 1282 mdb_printf("selector_unit Descriptor\n"); 1283 print_descr(addr, nlen, 1284 usb_ac_selector_descr, usb_ac_selector_item); 1285 1286 break; 1287 case 0x06: 1288 mdb_printf("feature_unit Descriptor\n"); 1289 print_descr(addr, nlen, 1290 usb_ac_feature_descr, usb_ac_feature_item); 1291 1292 break; 1293 case 0x07: 1294 mdb_printf("processing_unit Descriptor\n"); 1295 print_descr(addr, nlen, 1296 usb_ac_processing_descr, usb_ac_processing_item); 1297 1298 break; 1299 case 0x08: 1300 mdb_printf("extension_unit Descriptor\n"); 1301 print_descr(addr, nlen, 1302 usb_ac_extension_descr, usb_ac_extension_item); 1303 1304 break; 1305 default: 1306 mdb_printf("Unknown AC sub-descriptor 0x%x\n", sub_type); 1307 prt_usb_buf(addr, nlen); 1308 1309 break; 1310 } 1311 1312 return (DCMD_OK); 1313 } 1314 1315 /* print audio class specific stream descriptor */ 1316 static int 1317 prt_usb_as_desc(uintptr_t addr, uint_t nlen) 1318 { 1319 uchar_t sub_type; 1320 1321 if (mdb_vread(&sub_type, 1, addr + 2) == -1) { 1322 1323 return (DCMD_ERR); 1324 } 1325 switch (sub_type) { 1326 case 0x01: 1327 mdb_printf("general_interface Descriptor\n"); 1328 print_descr(addr, nlen, 1329 usb_as_if_descr, usb_as_if_item); 1330 1331 break; 1332 case 0x02: 1333 mdb_printf("format_type Descriptor\n"); 1334 print_descr(addr, nlen, 1335 usb_as_format_descr, usb_as_format_item); 1336 1337 break; 1338 default: 1339 mdb_printf("Unknown AS sub-descriptor 0x%x\n", sub_type); 1340 prt_usb_buf(addr, nlen); 1341 1342 break; 1343 } 1344 1345 return (DCMD_OK); 1346 } 1347 1348 /* print video class specific control descriptor */ 1349 static int 1350 prt_usb_vc_desc(uintptr_t addr, uint_t nlen) 1351 { 1352 uchar_t sub_type; 1353 1354 if (mdb_vread(&sub_type, 1, addr + 2) == -1) { 1355 1356 return (DCMD_ERR); 1357 } 1358 switch (sub_type) { 1359 case 0x01: 1360 mdb_printf("header Descriptor\n"); 1361 print_descr(addr, nlen, 1362 usb_vc_header_descr, usb_vc_header_item); 1363 1364 break; 1365 case 0x02: 1366 mdb_printf("input_terminal Descriptor\n"); 1367 print_descr(addr, nlen, 1368 usb_vc_input_term_descr, usb_vc_input_term_item); 1369 1370 break; 1371 case 0x03: 1372 mdb_printf("output_terminal Descriptor\n"); 1373 print_descr(addr, nlen, 1374 usb_vc_output_term_descr, usb_vc_output_term_item); 1375 1376 break; 1377 case 0x04: 1378 mdb_printf("selector_unit Descriptor\n"); 1379 print_descr(addr, nlen, 1380 usb_vc_selector_descr, usb_vc_selector_item); 1381 1382 break; 1383 case 0x05: 1384 mdb_printf("processing_unit Descriptor\n"); 1385 print_descr(addr, nlen, 1386 usb_vc_processing_descr, usb_vc_processing_item); 1387 1388 break; 1389 case 0x06: 1390 mdb_printf("extension_unit Descriptor\n"); 1391 print_descr(addr, nlen, 1392 usb_vc_extension_descr, usb_vc_extension_item); 1393 1394 break; 1395 default: 1396 mdb_printf("Unknown VC sub-descriptor 0x%x\n", sub_type); 1397 prt_usb_buf(addr, nlen); 1398 1399 break; 1400 } 1401 1402 return (DCMD_OK); 1403 } 1404 1405 /* print video class specific stream descriptor */ 1406 static int 1407 prt_usb_vs_desc(uintptr_t addr, uint_t nlen) 1408 { 1409 uchar_t sub_type; 1410 1411 if (mdb_vread(&sub_type, 1, addr + 2) == -1) { 1412 1413 return (DCMD_ERR); 1414 } 1415 switch (sub_type) { 1416 case 0x01: 1417 mdb_printf("input_header Descriptor\n"); 1418 print_descr(addr, nlen, 1419 usb_vs_input_header_descr, usb_vs_input_header_item); 1420 1421 break; 1422 case 0x02: 1423 mdb_printf("output_header Descriptor\n"); 1424 print_descr(addr, nlen, 1425 usb_vs_output_header_descr, usb_vs_output_header_item); 1426 1427 break; 1428 case 0x03: 1429 mdb_printf("still_image_frame Descriptor\n"); 1430 print_descr(addr, nlen, 1431 usb_vs_still_image_descr, usb_vs_still_image_item); 1432 1433 break; 1434 case 0x04: 1435 mdb_printf("format_uncompressed Descriptor\n"); 1436 print_descr(addr, nlen, 1437 usb_vs_format_uncps_descr, usb_vs_format_uncps_item); 1438 1439 break; 1440 case 0x05: 1441 mdb_printf("frame_uncompressed Descriptor\n"); 1442 print_descr(addr, nlen, 1443 usb_vs_2frame_descr, usb_vs_2frame_item); 1444 1445 break; 1446 case 0x06: 1447 mdb_printf("format_mjpeg Descriptor\n"); 1448 print_descr(addr, nlen, 1449 usb_vs_format_mjpeg_descr, usb_vs_format_mjpeg_item); 1450 1451 break; 1452 case 0x07: 1453 mdb_printf("frame_mjpeg Descriptor\n"); 1454 print_descr(addr, nlen, 1455 usb_vs_2frame_descr, usb_vs_2frame_item); 1456 1457 break; 1458 case 0x0A: 1459 mdb_printf("format_mpeg2ts Descriptor\n"); 1460 print_descr(addr, nlen, 1461 usb_vs_format_mp2ts_descr, usb_vs_format_mp2ts_item); 1462 1463 break; 1464 case 0x0C: 1465 mdb_printf("format_dv Descriptor\n"); 1466 print_descr(addr, nlen, 1467 usb_vs_format_dv_descr, usb_vs_format_dv_item); 1468 1469 break; 1470 case 0x0D: 1471 mdb_printf("color_matching Descriptor\n"); 1472 print_descr(addr, nlen, 1473 usb_vs_color_matching_descr, usb_vs_color_matching_item); 1474 1475 break; 1476 default: 1477 mdb_printf("Unknown VS sub-descriptor 0x%x\n", sub_type); 1478 prt_usb_buf(addr, nlen); 1479 1480 break; 1481 } 1482 1483 return (DCMD_OK); 1484 } 1485 1486 /* parse and print the descriptor items */ 1487 static int 1488 print_descr(uintptr_t addr, uint_t nlen, usb_descr_item_t *item, uint_t nitem) 1489 { 1490 int i, j; 1491 uint8_t buf[8]; 1492 uint64_t value; 1493 uintptr_t paddr = addr; 1494 usb_descr_item_t *p = item; 1495 1496 mdb_printf("{"); 1497 for (i = 0; (i < nitem) && (paddr < addr + nlen); i++) { 1498 mdb_printf("\n %s =", p->name); 1499 switch (p->nlen) { 1500 case 1: /* uint8_t */ 1501 if (mdb_vread(buf, 1, paddr) == -1) { 1502 1503 return (DCMD_ERR); 1504 } 1505 value = buf[0]; 1506 1507 break; 1508 case 2: /* uint16_t */ 1509 if (mdb_vread(buf, 2, paddr) == -1) { 1510 1511 return (DCMD_ERR); 1512 } 1513 value = buf[0] | (buf[1] << 8); 1514 1515 break; 1516 case 4: /* uint32_t */ 1517 if (mdb_vread(buf, 4, paddr) == -1) { 1518 1519 return (DCMD_ERR); 1520 } 1521 value = buf[0] | (buf[1] << 8) | 1522 (buf[2] << 16) | (buf[3] << 24); 1523 1524 break; 1525 case 8: /* uint64_t */ 1526 if (mdb_vread(buf, 8, paddr) == -1) { 1527 1528 return (DCMD_ERR); 1529 } 1530 value = buf[4] | (buf[5] << 8) | 1531 (buf[6] << 16) | (buf[7] << 24); 1532 value = buf[0] | (buf[1] << 8) | 1533 (buf[2] << 16) | (buf[3] << 24) | 1534 (value << 32); 1535 1536 break; 1537 default: /* byte array */ 1538 value = 0; 1539 /* print an array instead of a value */ 1540 for (j = 0; j < p->nlen - BYTE_OFFSET; j++) { 1541 if (mdb_vread(buf, 1, paddr + j) == -1) { 1542 1543 break; 1544 } 1545 mdb_printf(" 0x%x", buf[0]); 1546 } 1547 1548 break; 1549 } 1550 1551 if (p->nlen > BYTE_OFFSET) { 1552 paddr += p->nlen - BYTE_OFFSET; 1553 } else { 1554 mdb_printf(" 0x%x", value); 1555 paddr += p->nlen; 1556 } 1557 1558 p++; 1559 } 1560 1561 /* print the unresolved bytes */ 1562 if (paddr < addr + nlen) { 1563 mdb_printf("\n ... ="); 1564 } 1565 while (paddr < addr + nlen) { 1566 if (mdb_vread(buf, 1, paddr++) == -1) { 1567 1568 break; 1569 } 1570 mdb_printf(" 0x%x", buf[0]); 1571 } 1572 mdb_printf("\n}\n"); 1573 1574 return (DCMD_OK); 1575 } 1576 1577 /* print the buffer as a struct */ 1578 static int 1579 print_struct(uintptr_t addr, uint_t nlen, mdb_arg_t *arg) 1580 { 1581 mdb_ctf_id_t id; 1582 if (mdb_ctf_lookup_by_name(arg->a_un.a_str, &id) == 0) { 1583 1584 mdb_call_dcmd("print", addr, DCMD_ADDRSPEC, 1, arg); 1585 } else { 1586 1587 prt_usb_buf(addr, nlen); 1588 } 1589 1590 return (DCMD_OK); 1591 } 1592 1593 /* print the buffer as a byte array */ 1594 static int 1595 prt_usb_buf(uintptr_t addr, uint_t nlen) 1596 { 1597 int i; 1598 uchar_t val; 1599 1600 mdb_printf("{\n"); 1601 for (i = 0; i < nlen; i++) { 1602 if (mdb_vread(&val, 1, addr + i) == -1) { 1603 1604 break; 1605 } 1606 mdb_printf("%02x ", val); 1607 } 1608 if (nlen) { 1609 mdb_printf("\n"); 1610 } 1611 mdb_printf("}\n"); 1612 1613 return (DCMD_OK); 1614 } 1615