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
prt_usb_usage(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
prtusb(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
prt_usb_tree(uintptr_t paddr,uint_t flag)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
prt_usb_tree_node(uintptr_t paddr)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
prt_usb_hid_item(uintptr_t paddr)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
prt_usb_hid_item_params(entity_item_t * item)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
prt_usb_hid_item_attrs(uintptr_t paddr)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
prt_usb_hid_item_data(uintptr_t paddr,uint_t len)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
prt_usb_hid_item_tags(uint_t tag)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
prt_usb_desc(uintptr_t usb_cfg,uint_t cfg_len)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
prt_usb_ac_desc(uintptr_t addr,uint_t nlen)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
prt_usb_as_desc(uintptr_t addr,uint_t nlen)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
prt_usb_vc_desc(uintptr_t addr,uint_t nlen)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
prt_usb_vs_desc(uintptr_t addr,uint_t nlen)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
print_descr(uintptr_t addr,uint_t nlen,usb_descr_item_t * item,uint_t nitem)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
print_struct(uintptr_t addr,uint_t nlen,mdb_arg_t * arg)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
prt_usb_buf(uintptr_t addr,uint_t nlen)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