#include #include #include #include #include #include #include #include #include int verbose = 0; int language = 0; void show_device_desc(int indent, usb_device_descriptor_t *d) { printf("\ %*sbLength=%d bDescriptorType=%d bcdUSB=%x.%02x bDeviceClass=%d bDeviceSubClass=%d\n\ %*sbDeviceProtocol=%d bMaxPacketSize=%d\n\ %*sidVendor=0x%04x idProduct=0x%04x bcdDevice=%x\n\ %*siManufacturer=%d iProduct=%d iSerialNumber=%d bNumConfigurations=%d\n", indent, "", d->bLength, d->bDescriptorType, UGETW(d->bcdUSB) >> 8, UGETW(d->bcdUSB) & 0xff, d->bDeviceClass, d->bDeviceSubClass, indent, "", d->bDeviceProtocol, d->bMaxPacketSize, indent, "", UGETW(d->idVendor), UGETW(d->idProduct), UGETW(d->bcdDevice), indent, "", d->iManufacturer, d->iProduct, d->iSerialNumber, d->bNumConfigurations); } void show_config_desc(int indent, usb_config_descriptor_t *d) { printf("\ %*sbLength=%d bDescriptorType=%d wTotalLength=%d bNumInterface=%d\n\ %*sbConfigurationValue=%d iConfiguration=%d bmAttributes=%x bMaxPower=%d mA\n", indent, "", d->bLength, d->bDescriptorType, UGETW(d->wTotalLength), d->bNumInterface, indent, "", d->bConfigurationValue, d->iConfiguration, d->bmAttributes, d->bMaxPower*2); } void show_interface_desc(int indent, usb_interface_descriptor_t *d) { printf("\ %*sbLength=%d bDescriptorType=%d bInterfaceNumber=%d bAlternateSetting=%d\n\ %*sbNumEndpoints=%d bInterfaceClass=%d bInterfaceSubClass=%d\n\ %*sbInterfaceProtocol=%d iInterface=%d\n", indent, "", d->bLength, d->bDescriptorType, d->bInterfaceNumber, d->bAlternateSetting, indent, "", d->bNumEndpoints, d->bInterfaceClass, d->bInterfaceSubClass, indent, "", d->bInterfaceProtocol, d->iInterface); } void show_endpoint_desc(int indent, usb_endpoint_descriptor_t *d) { printf("\ %*sbLength=%d bDescriptorType=%d bEndpointAddress=%d-%s\n\ %*sbmAttributes=%x wMaxPacketSize=%d bInterval=%d\n", indent, "", d->bLength, d->bDescriptorType, d->bEndpointAddress & UE_ADDR, d->bEndpointAddress & UE_DIR_IN ? "in" : "out", indent, "", d->bmAttributes, UGETW(d->wMaxPacketSize), d->bInterval); } void set_conf(int f, int conf) { if (verbose) printf("setting configuration %d\n", conf); if (ioctl(f, USB_SET_CONFIG, &conf) != 0) err(1, "ioctl USB_SET_CONFIG"); } void dump_idesc(int f, int all, int cindex, int iindex, int aindex) { struct usb_interface_desc idesc; struct usb_endpoint_desc edesc; int e; idesc.uid_config_index = cindex; idesc.uid_interface_index = iindex; idesc.uid_alt_index = aindex; /*printf("*** idesc %d %d %d\n", cindex, iindex, aindex);*/ if (ioctl(f, USB_GET_INTERFACE_DESC, &idesc) != 0) err(1, "ioctl USB_GET_INTERFACE_DESC"); if (all) { printf(" INTERFACE descriptor index %d, alt index %d:\n", iindex, aindex); } else { printf(" INTERFACE descriptor index %d:\n", iindex); } show_interface_desc(2, &idesc.uid_desc); printf("\n"); edesc.ued_config_index = cindex; edesc.ued_interface_index = iindex; edesc.ued_alt_index = aindex; for (e = 0; e < idesc.uid_desc.bNumEndpoints; e++) { edesc.ued_endpoint_index = e; if (ioctl(f, USB_GET_ENDPOINT_DESC, &edesc) != 0) err(1, "ioctl USB_GET_ENDPOINT_DESC"); printf(" ENDPOINT descriptor index %d:\n", e); show_endpoint_desc(4, &edesc.ued_desc); printf("\n"); } } void dump_cdesc(int f, int all, int cindex) { struct usb_config_desc cdesc; struct usb_alt_interface ai; int i, a; cdesc.ucd_config_index = cindex; if (ioctl(f, USB_GET_CONFIG_DESC, &cdesc) != 0) err(1, "ioctl USB_GET_CONFIG_DESC"); if (all) printf("CONFIGURATION descriptor index %d:\n", cindex); else printf("CONFIGURATION descriptor:\n"); show_config_desc(0, &cdesc.ucd_desc); printf("\n"); for (i = 0; i < cdesc.ucd_desc.bNumInterface; i++) { if (all) { #if 0 if (ioctl(f, USB_GET_ALTINTERFACE, &ai) != 0) err(1, "USB_GET_ALTINTERFACE"); printf("Current alternative %d\n", ai->alt_no); #endif ai.uai_config_index = cindex; ai.uai_interface_index = i; if (ioctl(f, USB_GET_NO_ALT, &ai) != 0) err(1, "USB_GET_NO_ALT"); /*printf("*** %d alts\n", ai.alt_no);*/ for (a = 0; a < ai.uai_alt_no; a++) dump_idesc(f, all, cindex, i, a); } else { dump_idesc(f, all, cindex, i, USB_CURRENT_ALT_INDEX); } } } void dump_desc(int f, int all) { usb_device_descriptor_t ddesc; int c, co; if (verbose) printf("Dumping %s descriptors\n", all ? "all" : "current"); if (ioctl(f, USB_GET_DEVICE_DESC, &ddesc) != 0) err(1, "ioctl USB_GET_DEVICE_DESC"); printf("DEVICE descriptor:\n"); show_device_desc(0, &ddesc); printf("\n"); if (all) { if (ioctl(f, USB_GET_CONFIG, &co) != 0) err(1, "ioctl USB_GET_CONFIG"); printf("Current configuration is number %d\n\n", co); for (c = 0; c < ddesc.bNumConfigurations; c++) dump_cdesc(f, all, c); } else dump_cdesc(f, all, USB_CURRENT_CONFIG_INDEX); } void dump_stringdesc(int f, int index) { struct usb_string_desc sdesc; int i; int c; sdesc.usd_string_index = index; sdesc.usd_language_id = language; if (ioctl(f, USB_GET_STRING_DESC, &sdesc) != 0) err(1, "ioctl USB_GET_STRING_DESC"); if (index == 0) { printf("string 0 (languages): "); for (i = 0; i < sdesc.usd_desc.bLength / 2 - 1; i++) { c = UGETW(sdesc.usd_desc.bString[i]); printf("0x%02x (%d) ", c, c); } printf("\n"); } else { printf("string %d: '", index); for (i = 0; i < sdesc.usd_desc.bLength / 2 - 1; i++) { c = UGETW(sdesc.usd_desc.bString[i]); printf("%c", c & 0x00ff); } printf("'\n"); } } void dump_deviceinfo(int f) { struct usb_device_info di; if (ioctl(f, USB_GET_DEVICEINFO, &di) != 0) err(1, "USB_GET_DEVICEINFO"); printf("Product: %s\n", di.udi_product); printf("Vendor: %s\n", di.udi_vendor); printf("address %d\n", di.udi_addr); } void usage(void) { extern char *__progname; fprintf(stderr, "Usage: %s [-c configno] [-i] [-d] [-D] [-l languageId] [-s stringIndex] -f device [-v]\n", __progname); exit(1); } int main(int argc, char **argv) { char *dev = 0; char devbuf[1024] = ""; int f, ch, i; /* Find device first */ for (i = 1; i < argc-1; i++) { if (strcmp(argv[i], "-f") == 0) { dev = argv[i+1]; } else if (strcmp(argv[i], "-v") == 0) { verbose = 1; } } if (!dev) usage(); f = open(dev, O_RDWR); if (f < 0 && dev[0] != '/') { sprintf(devbuf, "/dev/%s", dev); f = open(devbuf, O_RDWR); if (f < 0 && !strchr(devbuf, '.')) { strcat(devbuf, ".00"); f = open(devbuf, O_RDWR); } } if (f < 0) err(1, "%s", dev); if (devbuf[0] == '\0') strcpy(devbuf, dev); if (verbose) printf("%s Opened\n", devbuf? devbuf:dev); while ((ch = getopt(argc, argv, "c:dDf:ivs:l:")) != -1) { switch(ch) { case 'c': set_conf(f, atoi(optarg)); break; case 'd': dump_desc(f, 0); break; case 'D': dump_desc(f, 1); break; case 'f': /* already handled (above) */ break; case 'l': language = atoi(optarg); break; case 'i': dump_deviceinfo(f); printf("\n"); break; case 's': dump_stringdesc(f, atoi(optarg)); break; case 'v': break; case '?': default: usage(); } } argc -= optind; argv += optind; exit(0); }