3 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 #include <libusb20_desc.h>
43 #define DUMP0(n,type,field,...) dump_field(pdev, " ", #field, n->field);
44 #define DUMP1(n,type,field,...) dump_field(pdev, " ", #field, n->field);
45 #define DUMP2(n,type,field,...) dump_field(pdev, " ", #field, n->field);
46 #define DUMP3(n,type,field,...) dump_field(pdev, " ", #field, n->field);
49 dump_mode(uint8_t value)
51 if (value == LIBUSB20_MODE_HOST)
57 dump_speed(uint8_t value)
61 case LIBUSB20_SPEED_LOW:
62 return ("LOW (1.5Mbps)");
63 case LIBUSB20_SPEED_FULL:
64 return ("FULL (12Mbps)");
65 case LIBUSB20_SPEED_HIGH:
66 return ("HIGH (480Mbps)");
67 case LIBUSB20_SPEED_VARIABLE:
68 return ("VARIABLE (52-480Mbps)");
69 case LIBUSB20_SPEED_SUPER:
70 return ("SUPER (5.0Gbps)");
74 return ("UNKNOWN ()");
78 dump_power_mode(uint8_t value)
82 case LIBUSB20_POWER_OFF:
84 case LIBUSB20_POWER_ON:
86 case LIBUSB20_POWER_SAVE:
88 case LIBUSB20_POWER_SUSPEND:
90 case LIBUSB20_POWER_RESUME:
98 dump_field(struct libusb20_device *pdev, const char *plevel,
99 const char *field, uint32_t value)
101 uint8_t temp_string[256];
103 printf("%s%s = 0x%04x ", plevel, field, value);
105 if (strlen(plevel) == 8) {
106 /* Endpoint Descriptor */
108 if (strcmp(field, "bEndpointAddress") == 0) {
115 if (strcmp(field, "bmAttributes") == 0) {
116 switch (value & 0x03) {
118 printf(" <CONTROL>\n");
121 switch (value & 0x0C) {
123 printf(" <ISOCHRONOUS>\n");
126 printf(" <ASYNC-ISOCHRONOUS>\n");
129 printf(" <ADAPT-ISOCHRONOUS>\n");
132 printf(" <SYNC-ISOCHRONOUS>\n");
140 printf(" <INTERRUPT>\n");
146 if ((field[0] == 'i') && (field[1] != 'd')) {
147 /* Indirect String Descriptor */
149 printf(" <no string>\n");
152 if (libusb20_dev_req_string_simple_sync(pdev, value,
153 temp_string, sizeof(temp_string))) {
154 printf(" <retrieving string failed>\n");
157 printf(" <%s>\n", temp_string);
160 if (strlen(plevel) == 2 || strlen(plevel) == 6) {
162 /* Device and Interface Descriptor class codes */
164 if (strcmp(field, "bInterfaceClass") == 0 ||
165 strcmp(field, "bDeviceClass") == 0) {
169 printf(" <Probed by interface class>\n");
172 printf(" <Audio device>\n");
175 printf(" <Communication device>\n");
178 printf(" <HID device>\n");
181 printf(" <Physical device>\n");
184 printf(" <Still imaging>\n");
187 printf(" <Printer device>\n");
190 printf(" <Mass storage>\n");
196 printf(" <CDC-data>\n");
199 printf(" <Smart card>\n");
202 printf(" <Content security>\n");
205 printf(" <Video device>\n");
208 printf(" <Personal healthcare>\n");
211 printf(" <Audio and video device>\n");
214 printf(" <Billboard device>\n");
217 printf(" <Diagnostic device>\n");
220 printf(" <Wireless controller>\n");
223 printf(" <Miscellaneous device>\n");
226 printf(" <Application specific>\n");
229 printf(" <Vendor specific>\n");
232 printf(" <Unknown>\n");
238 /* No additional information */
243 dump_extra(struct libusb20_me_struct *str, const char *plevel)
250 while ((ptr = libusb20_desc_foreach(str, ptr))) {
251 printf("\n" "%sAdditional Descriptor\n\n", plevel);
252 printf("%sbLength = 0x%02x\n", plevel, ptr[0]);
253 printf("%sbDescriptorType = 0x%02x\n", plevel, ptr[1]);
255 printf("%sbDescriptorSubType = 0x%02x\n",
257 printf("%s RAW dump: ", plevel);
258 for (x = 0; x != ptr[0]; x++) {
260 printf("\n%s 0x%02x | ", plevel, x);
262 printf("0x%02x%s", ptr[x],
263 (x != (ptr[0] - 1)) ? ", " : (x % 8) ? "\n" : "");
271 dump_endpoint(struct libusb20_device *pdev,
272 struct libusb20_endpoint *ep)
274 struct LIBUSB20_ENDPOINT_DESC_DECODED *edesc;
277 LIBUSB20_ENDPOINT_DESC(DUMP3, edesc);
278 dump_extra(&ep->extra, " " " " " ");
283 dump_iface(struct libusb20_device *pdev,
284 struct libusb20_interface *iface)
286 struct LIBUSB20_INTERFACE_DESC_DECODED *idesc;
289 idesc = &iface->desc;
290 LIBUSB20_INTERFACE_DESC(DUMP2, idesc);
291 dump_extra(&iface->extra, " " " " " ");
293 for (z = 0; z != iface->num_endpoints; z++) {
294 printf("\n Endpoint %u\n", z);
295 dump_endpoint(pdev, iface->endpoints + z);
301 dump_device_info(struct libusb20_device *pdev, uint8_t show_ifdrv)
307 usage = libusb20_dev_get_power_usage(pdev);
309 printf("%s, cfg=%u md=%s spd=%s pwr=%s (%umA)\n",
310 libusb20_dev_get_desc(pdev),
311 libusb20_dev_get_config_index(pdev),
312 dump_mode(libusb20_dev_get_mode(pdev)),
313 dump_speed(libusb20_dev_get_speed(pdev)),
314 dump_power_mode(libusb20_dev_get_power_mode(pdev)),
320 for (n = 0; n != 255; n++) {
321 if (libusb20_dev_get_iface_desc(pdev, n, buf, sizeof(buf)))
325 printf("ugen%u.%u.%u: %s\n",
326 libusb20_dev_get_bus_number(pdev),
327 libusb20_dev_get_address(pdev), n, buf);
332 dump_be_quirk_names(struct libusb20_backend *pbe)
334 struct libusb20_quirk q;
338 memset(&q, 0, sizeof(q));
340 printf("\nDumping list of supported quirks:\n\n");
342 for (x = 0; x != 0xFFFF; x++) {
344 error = libusb20_be_get_quirk_name(pbe, x, &q);
347 printf("No quirk names - maybe the USB quirk "
348 "module has not been loaded.\n");
352 if (strcmp(q.quirkname, "UQ_NONE"))
353 printf("%s\n", q.quirkname);
360 dump_be_dev_quirks(struct libusb20_backend *pbe)
362 struct libusb20_quirk q;
366 memset(&q, 0, sizeof(q));
368 printf("\nDumping current device quirks:\n\n");
370 for (x = 0; x != 0xFFFF; x++) {
372 error = libusb20_be_get_dev_quirk(pbe, x, &q);
375 printf("No device quirks - maybe the USB quirk "
376 "module has not been loaded.\n");
380 if (strcmp(q.quirkname, "UQ_NONE")) {
381 printf("VID=0x%04x PID=0x%04x REVLO=0x%04x "
382 "REVHI=0x%04x QUIRK=%s\n",
383 q.vid, q.pid, q.bcdDeviceLow,
384 q.bcdDeviceHigh, q.quirkname);
392 dump_device_desc(struct libusb20_device *pdev)
394 struct LIBUSB20_DEVICE_DESC_DECODED *ddesc;
396 ddesc = libusb20_dev_get_device_desc(pdev);
397 LIBUSB20_DEVICE_DESC(DUMP0, ddesc);
402 dump_config(struct libusb20_device *pdev, uint8_t all_cfg)
404 struct LIBUSB20_CONFIG_DESC_DECODED *cdesc;
405 struct LIBUSB20_DEVICE_DESC_DECODED *ddesc;
406 struct libusb20_config *pcfg = NULL;
408 uint8_t cfg_index_end;
412 ddesc = libusb20_dev_get_device_desc(pdev);
416 cfg_index_end = ddesc->bNumConfigurations;
418 cfg_index = libusb20_dev_get_config_index(pdev);
419 cfg_index_end = cfg_index + 1;
422 for (; cfg_index != cfg_index_end; cfg_index++) {
424 pcfg = libusb20_dev_alloc_config(pdev, cfg_index);
428 printf("\n Configuration index %u\n\n", cfg_index);
429 cdesc = &(pcfg->desc);
430 LIBUSB20_CONFIG_DESC(DUMP1, cdesc);
431 dump_extra(&(pcfg->extra), " " " ");
433 for (x = 0; x != pcfg->num_interface; x++) {
434 printf("\n Interface %u\n", x);
435 dump_iface(pdev, pcfg->interface + x);
437 for (y = 0; y != (pcfg->interface + x)->num_altsetting; y++) {
438 printf("\n Interface %u Alt %u\n", x, y + 1);
440 (pcfg->interface + x)->altsetting + y);
451 dump_string_by_index(struct libusb20_device *pdev, uint8_t str_index)
459 err(1, "out of memory");
461 if (str_index == 0) {
463 if (libusb20_dev_req_string_sync(pdev,
464 str_index, 0, pbuf, 256)) {
465 printf("STRING_0x%02x = <read error>\n", str_index);
467 printf("STRING_0x%02x = ", str_index);
468 len = (uint8_t)pbuf[0];
469 for (n = 0; n != len; n++) {
470 printf("0x%02x%s", (uint8_t)pbuf[n],
471 (n != (len - 1)) ? ", " : "");
476 /* ordinary string */
477 if (libusb20_dev_req_string_simple_sync(pdev,
478 str_index, pbuf, 256)) {
479 printf("STRING_0x%02x = <read error>\n", str_index);
481 printf("STRING_0x%02x = <%s>\n", str_index, pbuf);