dump.c revision 198833
1254885Sdumbbell/* $FreeBSD: head/usr.sbin/usbconfig/dump.c 198833 2009-11-02 23:50:12Z thompsa $ */ 2254885Sdumbbell/*- 3254885Sdumbbell * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 4254885Sdumbbell * 5254885Sdumbbell * Redistribution and use in source and binary forms, with or without 6254885Sdumbbell * modification, are permitted provided that the following conditions 7254885Sdumbbell * are met: 8254885Sdumbbell * 1. Redistributions of source code must retain the above copyright 9254885Sdumbbell * notice, this list of conditions and the following disclaimer. 10254885Sdumbbell * 2. Redistributions in binary form must reproduce the above copyright 11254885Sdumbbell * notice, this list of conditions and the following disclaimer in the 12254885Sdumbbell * documentation and/or other materials provided with the distribution. 13254885Sdumbbell * 14254885Sdumbbell * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15254885Sdumbbell * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16254885Sdumbbell * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17254885Sdumbbell * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18254885Sdumbbell * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19254885Sdumbbell * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20254885Sdumbbell * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21254885Sdumbbell * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22254885Sdumbbell * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23254885Sdumbbell * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24254885Sdumbbell * SUCH DAMAGE. 25254885Sdumbbell */ 26254885Sdumbbell 27254885Sdumbbell#include <stdio.h> 28254885Sdumbbell#include <stdlib.h> 29254885Sdumbbell#include <stdint.h> 30254885Sdumbbell#include <err.h> 31254885Sdumbbell#include <string.h> 32254885Sdumbbell#include <pwd.h> 33254885Sdumbbell#include <grp.h> 34266594Sdumbbell#include <ctype.h> 35254885Sdumbbell 36266594Sdumbbell#include <libusb20.h> 37266594Sdumbbell#include <libusb20_desc.h> 38266594Sdumbbell 39266594Sdumbbell#include "dump.h" 40266594Sdumbbell 41254885Sdumbbell#define DUMP0(n,type,field,...) dump_field(pdev, " ", #field, n->field); 42254885Sdumbbell#define DUMP1(n,type,field,...) dump_field(pdev, " ", #field, n->field); 43254885Sdumbbell#define DUMP2(n,type,field,...) dump_field(pdev, " ", #field, n->field); 44254885Sdumbbell#define DUMP3(n,type,field,...) dump_field(pdev, " ", #field, n->field); 45254885Sdumbbell 46254885Sdumbbellconst char * 47254885Sdumbbelldump_mode(uint8_t value) 48254885Sdumbbell{ 49254885Sdumbbell if (value == LIBUSB20_MODE_HOST) 50254885Sdumbbell return ("HOST"); 51254885Sdumbbell return ("DEVICE"); 52254885Sdumbbell} 53254885Sdumbbell 54254885Sdumbbellconst char * 55254885Sdumbbelldump_speed(uint8_t value) 56254885Sdumbbell{ 57254885Sdumbbell ; /* style fix */ 58254885Sdumbbell switch (value) { 59254885Sdumbbell case LIBUSB20_SPEED_LOW: 60254885Sdumbbell return ("LOW (1.5Mbps)"); 61254885Sdumbbell case LIBUSB20_SPEED_FULL: 62254885Sdumbbell return ("FULL (12Mbps)"); 63254885Sdumbbell case LIBUSB20_SPEED_HIGH: 64254885Sdumbbell return ("HIGH (480Mbps)"); 65254885Sdumbbell case LIBUSB20_SPEED_VARIABLE: 66266594Sdumbbell return ("VARIABLE (52-480Mbps)"); 67266594Sdumbbell case LIBUSB20_SPEED_SUPER: 68254885Sdumbbell return ("SUPER (4.8Gbps)"); 69266594Sdumbbell default: 70266594Sdumbbell break; 71254885Sdumbbell } 72266594Sdumbbell return ("unknown"); 73254885Sdumbbell} 74266594Sdumbbell 75266594Sdumbbellconst char * 76266594Sdumbbelldump_power_mode(uint8_t value) 77266594Sdumbbell{ 78266594Sdumbbell ; /* style fix */ 79266594Sdumbbell switch (value) { 80266594Sdumbbell case LIBUSB20_POWER_OFF: 81266594Sdumbbell return ("OFF"); 82266594Sdumbbell case LIBUSB20_POWER_ON: 83266594Sdumbbell return ("ON"); 84266594Sdumbbell case LIBUSB20_POWER_SAVE: 85266594Sdumbbell return ("SAVE"); 86266594Sdumbbell case LIBUSB20_POWER_SUSPEND: 87266594Sdumbbell return ("SUSPEND"); 88266594Sdumbbell case LIBUSB20_POWER_RESUME: 89266594Sdumbbell return ("RESUME"); 90266594Sdumbbell default: 91266594Sdumbbell return ("UNKNOWN"); 92266594Sdumbbell } 93266594Sdumbbell} 94266594Sdumbbell 95254885Sdumbbellstatic void 96266594Sdumbbelldump_field(struct libusb20_device *pdev, const char *plevel, 97254885Sdumbbell const char *field, uint32_t value) 98254885Sdumbbell{ 99254885Sdumbbell uint8_t temp_string[256]; 100254885Sdumbbell 101254885Sdumbbell printf("%s%s = 0x%04x ", plevel, field, value); 102254885Sdumbbell 103254885Sdumbbell if (strlen(plevel) == 8) { 104254885Sdumbbell /* Endpoint Descriptor */ 105254885Sdumbbell 106254885Sdumbbell if (strcmp(field, "bEndpointAddress") == 0) { 107254885Sdumbbell if (value & 0x80) 108266594Sdumbbell printf(" <IN>\n"); 109266594Sdumbbell else 110254885Sdumbbell printf(" <OUT>\n"); 111266594Sdumbbell return; 112266594Sdumbbell } 113254885Sdumbbell 114266594Sdumbbell if (strcmp(field, "bmAttributes") == 0) { 115254885Sdumbbell switch (value & 0x03) { 116266594Sdumbbell case 0: 117266594Sdumbbell printf(" <CONTROL>\n"); 118266594Sdumbbell break; 119266594Sdumbbell case 1: 120266594Sdumbbell switch (value & 0x0C) { 121266594Sdumbbell case 0x00: 122254885Sdumbbell printf(" <ISOCHRONOUS>\n"); 123266594Sdumbbell break; 124254885Sdumbbell case 0x04: 125254885Sdumbbell printf(" <ASYNC-ISOCHRONOUS>\n"); 126254885Sdumbbell break; 127254885Sdumbbell case 0x08: 128254885Sdumbbell printf(" <ADAPT-ISOCHRONOUS>\n"); 129254885Sdumbbell break; 130266594Sdumbbell default: 131266594Sdumbbell printf(" <SYNC-ISOCHRONOUS>\n"); 132254885Sdumbbell break; 133254885Sdumbbell } 134266594Sdumbbell break; 135254885Sdumbbell case 2: 136266594Sdumbbell printf(" <BULK>\n"); 137254885Sdumbbell break; 138266594Sdumbbell default: 139254885Sdumbbell printf(" <INTERRUPT>\n"); 140254885Sdumbbell break; 141254885Sdumbbell } 142254885Sdumbbell return; 143254885Sdumbbell } 144254885Sdumbbell } 145254885Sdumbbell 146254885Sdumbbell if ((field[0] == 'i') && (field[1] != 'd')) { 147254885Sdumbbell /* Indirect String Descriptor */ 148254885Sdumbbell if (value == 0) { 149254885Sdumbbell printf(" <no string>\n"); 150254885Sdumbbell return; 151254885Sdumbbell } 152254885Sdumbbell if (libusb20_dev_req_string_simple_sync(pdev, value, 153254885Sdumbbell temp_string, sizeof(temp_string))) { 154254885Sdumbbell printf(" <retrieving string failed>\n"); 155254885Sdumbbell return; 156266594Sdumbbell } 157266594Sdumbbell printf(" <%s>\n", temp_string); 158254885Sdumbbell return; 159266594Sdumbbell } 160266594Sdumbbell 161266594Sdumbbell /* No additional information */ 162266594Sdumbbell printf("\n"); 163254885Sdumbbell} 164266594Sdumbbell 165266594Sdumbbellstatic void 166254885Sdumbbelldump_extra(struct libusb20_me_struct *str, const char *plevel) 167266594Sdumbbell{ 168254885Sdumbbell const uint8_t *ptr; 169266594Sdumbbell uint8_t x; 170266594Sdumbbell 171266594Sdumbbell ptr = NULL; 172266594Sdumbbell 173266594Sdumbbell while ((ptr = libusb20_desc_foreach(str, ptr))) { 174266594Sdumbbell printf("\n" "%sAdditional Descriptor\n\n", plevel); 175266594Sdumbbell printf("%sbLength = 0x%02x\n", plevel, ptr[0]); 176266594Sdumbbell printf("%sbDescriptorType = 0x%02x\n", plevel, ptr[1]); 177266594Sdumbbell if (ptr[0] > 1) 178266594Sdumbbell printf("%sbDescriptorSubType = 0x%02x\n", 179266594Sdumbbell plevel, ptr[2]); 180254885Sdumbbell printf("%s RAW dump: ", plevel); 181266594Sdumbbell for (x = 0; x != ptr[0]; x++) { 182254885Sdumbbell if ((x % 8) == 0) { 183254885Sdumbbell printf("\n%s 0x%02x | ", plevel, x); 184254885Sdumbbell } 185254885Sdumbbell printf("0x%02x%s", ptr[x], 186254885Sdumbbell (x != (ptr[0] - 1)) ? ", " : (x % 8) ? "\n" : ""); 187254885Sdumbbell } 188254885Sdumbbell printf("\n"); 189254885Sdumbbell } 190254885Sdumbbell return; 191254885Sdumbbell} 192254885Sdumbbell 193266594Sdumbbellstatic void 194266594Sdumbbelldump_endpoint(struct libusb20_device *pdev, 195254885Sdumbbell struct libusb20_endpoint *ep) 196266594Sdumbbell{ 197266594Sdumbbell struct LIBUSB20_ENDPOINT_DESC_DECODED *edesc; 198254885Sdumbbell 199266594Sdumbbell edesc = &ep->desc; 200254885Sdumbbell LIBUSB20_ENDPOINT_DESC(DUMP3, edesc); 201266594Sdumbbell dump_extra(&ep->extra, " " " " " "); 202266594Sdumbbell return; 203266594Sdumbbell} 204266594Sdumbbell 205266594Sdumbbellstatic void 206266594Sdumbbelldump_iface(struct libusb20_device *pdev, 207254885Sdumbbell struct libusb20_interface *iface) 208266594Sdumbbell{ 209254885Sdumbbell struct LIBUSB20_INTERFACE_DESC_DECODED *idesc; 210254885Sdumbbell uint8_t z; 211254885Sdumbbell 212254885Sdumbbell idesc = &iface->desc; 213254885Sdumbbell LIBUSB20_INTERFACE_DESC(DUMP2, idesc); 214254885Sdumbbell dump_extra(&iface->extra, " " " " " "); 215254885Sdumbbell 216254885Sdumbbell for (z = 0; z != iface->num_endpoints; z++) { 217254885Sdumbbell printf("\n Endpoint %u\n", z); 218266594Sdumbbell dump_endpoint(pdev, iface->endpoints + z); 219266594Sdumbbell } 220254885Sdumbbell return; 221266594Sdumbbell} 222266594Sdumbbell 223254885Sdumbbellvoid 224266594Sdumbbelldump_device_info(struct libusb20_device *pdev, uint8_t show_ifdrv) 225254885Sdumbbell{ 226266594Sdumbbell char buf[128]; 227266594Sdumbbell uint8_t n; 228266594Sdumbbell 229266594Sdumbbell printf("%s, cfg=%u md=%s spd=%s pwr=%s\n", 230254885Sdumbbell libusb20_dev_get_desc(pdev), 231266594Sdumbbell libusb20_dev_get_config_index(pdev), 232254885Sdumbbell dump_mode(libusb20_dev_get_mode(pdev)), 233254885Sdumbbell dump_speed(libusb20_dev_get_speed(pdev)), 234254885Sdumbbell dump_power_mode(libusb20_dev_get_power_mode(pdev))); 235254885Sdumbbell 236254885Sdumbbell if (!show_ifdrv) 237254885Sdumbbell return; 238254885Sdumbbell 239266594Sdumbbell for (n = 0; n != 255; n++) { 240266594Sdumbbell if (libusb20_dev_get_iface_desc(pdev, n, buf, sizeof(buf))) 241254885Sdumbbell break; 242266594Sdumbbell if (buf[0] == 0) 243266594Sdumbbell continue; 244254885Sdumbbell printf("ugen%u.%u.%u: %s\n", 245266594Sdumbbell libusb20_dev_get_bus_number(pdev), 246254885Sdumbbell libusb20_dev_get_address(pdev), n, buf); 247266594Sdumbbell } 248266594Sdumbbell} 249254885Sdumbbell 250266594Sdumbbellvoid 251254885Sdumbbelldump_be_quirk_names(struct libusb20_backend *pbe) 252254885Sdumbbell{ 253254885Sdumbbell struct libusb20_quirk q; 254254885Sdumbbell uint16_t x; 255254885Sdumbbell int error; 256254885Sdumbbell 257254885Sdumbbell memset(&q, 0, sizeof(q)); 258254885Sdumbbell 259254885Sdumbbell printf("\nDumping list of supported quirks:\n\n"); 260266594Sdumbbell 261266594Sdumbbell for (x = 0; x != 0xFFFF; x++) { 262254885Sdumbbell 263266594Sdumbbell error = libusb20_be_get_quirk_name(pbe, x, &q); 264266594Sdumbbell if (error) { 265254885Sdumbbell if (x == 0) { 266266594Sdumbbell printf("No quirk names - maybe the USB quirk " 267254885Sdumbbell "module has not been loaded.\n"); 268266594Sdumbbell } 269266594Sdumbbell break; 270266594Sdumbbell } 271266594Sdumbbell if (strcmp(q.quirkname, "UQ_NONE")) 272254885Sdumbbell printf("%s\n", q.quirkname); 273266594Sdumbbell } 274254885Sdumbbell printf("\n"); 275254885Sdumbbell return; 276254885Sdumbbell} 277254885Sdumbbell 278254885Sdumbbellvoid 279254885Sdumbbelldump_be_dev_quirks(struct libusb20_backend *pbe) 280266594Sdumbbell{ 281266594Sdumbbell struct libusb20_quirk q; 282254885Sdumbbell uint16_t x; 283266594Sdumbbell int error; 284266594Sdumbbell 285254885Sdumbbell memset(&q, 0, sizeof(q)); 286266594Sdumbbell 287254885Sdumbbell printf("\nDumping current device quirks:\n\n"); 288266594Sdumbbell 289254885Sdumbbell for (x = 0; x != 0xFFFF; x++) { 290266594Sdumbbell 291254885Sdumbbell error = libusb20_be_get_dev_quirk(pbe, x, &q); 292254885Sdumbbell if (error) { 293254885Sdumbbell if (x == 0) { 294282199Sdumbbell printf("No device quirks - maybe the USB quirk " 295254885Sdumbbell "module has not been loaded.\n"); 296254885Sdumbbell } 297254885Sdumbbell break; 298254885Sdumbbell } 299254885Sdumbbell if (strcmp(q.quirkname, "UQ_NONE")) { 300266594Sdumbbell printf("VID=0x%04x PID=0x%04x REVLO=0x%04x " 301266594Sdumbbell "REVHI=0x%04x QUIRK=%s\n", 302254885Sdumbbell q.vid, q.pid, q.bcdDeviceLow, 303266594Sdumbbell q.bcdDeviceHigh, q.quirkname); 304266594Sdumbbell } 305254885Sdumbbell } 306266594Sdumbbell printf("\n"); 307254885Sdumbbell return; 308266594Sdumbbell} 309266594Sdumbbell 310254885Sdumbbellvoid 311266594Sdumbbelldump_device_desc(struct libusb20_device *pdev) 312254885Sdumbbell{ 313282199Sdumbbell struct LIBUSB20_DEVICE_DESC_DECODED *ddesc; 314282199Sdumbbell 315282199Sdumbbell ddesc = libusb20_dev_get_device_desc(pdev); 316254885Sdumbbell LIBUSB20_DEVICE_DESC(DUMP0, ddesc); 317266594Sdumbbell return; 318266594Sdumbbell} 319266594Sdumbbell 320266594Sdumbbellvoid 321266594Sdumbbelldump_config(struct libusb20_device *pdev, uint8_t all_cfg) 322266594Sdumbbell{ 323266594Sdumbbell struct LIBUSB20_CONFIG_DESC_DECODED *cdesc; 324266594Sdumbbell struct LIBUSB20_DEVICE_DESC_DECODED *ddesc; 325266594Sdumbbell struct libusb20_config *pcfg = NULL; 326266594Sdumbbell uint8_t cfg_index; 327266594Sdumbbell uint8_t cfg_index_end; 328254885Sdumbbell uint8_t x; 329282199Sdumbbell uint8_t y; 330254885Sdumbbell 331266594Sdumbbell ddesc = libusb20_dev_get_device_desc(pdev); 332 333 if (all_cfg) { 334 cfg_index = 0; 335 cfg_index_end = ddesc->bNumConfigurations; 336 } else { 337 cfg_index = libusb20_dev_get_config_index(pdev); 338 cfg_index_end = cfg_index + 1; 339 } 340 341 for (; cfg_index != cfg_index_end; cfg_index++) { 342 343 pcfg = libusb20_dev_alloc_config(pdev, cfg_index); 344 if (!pcfg) { 345 continue; 346 } 347 printf("\n Configuration index %u\n\n", cfg_index); 348 cdesc = &(pcfg->desc); 349 LIBUSB20_CONFIG_DESC(DUMP1, cdesc); 350 dump_extra(&(pcfg->extra), " " " "); 351 352 for (x = 0; x != pcfg->num_interface; x++) { 353 printf("\n Interface %u\n", x); 354 dump_iface(pdev, pcfg->interface + x); 355 printf("\n"); 356 for (y = 0; y != (pcfg->interface + x)->num_altsetting; y++) { 357 printf("\n Interface %u Alt %u\n", x, y + 1); 358 dump_iface(pdev, 359 (pcfg->interface + x)->altsetting + y); 360 printf("\n"); 361 } 362 } 363 printf("\n"); 364 free(pcfg); 365 } 366 return; 367} 368