void dump_config(struct libusb20_device *pdev, uint8_t all_cfg) { struct LIBUSB20_CONFIG_DESC_DECODED *cdesc; struct LIBUSB20_DEVICE_DESC_DECODED *ddesc; struct libusb20_config *pcfg = NULL; uint8_t cfg_index; uint8_t cfg_index_end; uint8_t x; uint8_t y; ddesc = libusb20_dev_get_device_desc(pdev); if (all_cfg) { cfg_index = 0; cfg_index_end = ddesc->bNumConfigurations; } else { cfg_index = libusb20_dev_get_config_index(pdev); cfg_index_end = cfg_index + 1; } for (; cfg_index != cfg_index_end; cfg_index++) { pcfg = libusb20_dev_alloc_config(pdev, cfg_index); if (!pcfg) { continue; } printf("\n Configuration index %u\n\n", cfg_index); cdesc = &(pcfg->desc); LIBUSB20_CONFIG_DESC(DUMP1, cdesc); dump_extra(&(pcfg->extra), " " " "); for (x = 0; x != pcfg->num_interface; x++) { printf("\n Interface %u\n", x); dump_iface(pdev, pcfg->interface + x); printf("\n"); for (y = 0; y != (pcfg->interface + x)->num_altsetting; y++) { printf("\n Interface %u Alt %u\n", x, y + 1); dump_iface(pdev, (pcfg->interface + x)->altsetting + y); printf("\n"); } } printf("\n"); free(pcfg); } return; }
int libusb_get_config_descriptor(libusb_device *dev, uint8_t config_index, struct libusb_config_descriptor **config) { struct libusb20_device *pdev; struct libusb20_config *pconf; struct libusb20_interface *pinf; struct libusb20_endpoint *pend; struct libusb_config_descriptor *pconfd; struct libusb_interface_descriptor *ifd; struct libusb_endpoint_descriptor *endd; uint8_t *pextra; uint16_t nextra; uint8_t nif; uint8_t nep; uint8_t nalt; uint8_t i; uint8_t j; uint8_t k; if (dev == NULL || config == NULL) return (LIBUSB_ERROR_INVALID_PARAM); *config = NULL; pdev = dev->os_priv; pconf = libusb20_dev_alloc_config(pdev, config_index); if (pconf == NULL) return (LIBUSB_ERROR_NOT_FOUND); nalt = nif = pconf->num_interface; nep = 0; nextra = N_ALIGN(pconf->extra.len); for (i = 0; i < nif; i++) { pinf = pconf->interface + i; nextra += N_ALIGN(pinf->extra.len); nep += pinf->num_endpoints; k = pinf->num_endpoints; pend = pinf->endpoints; while (k--) { nextra += N_ALIGN(pend->extra.len); pend++; } j = pinf->num_altsetting; nalt += pinf->num_altsetting; pinf = pinf->altsetting; while (j--) { nextra += N_ALIGN(pinf->extra.len); nep += pinf->num_endpoints; k = pinf->num_endpoints; pend = pinf->endpoints; while (k--) { nextra += N_ALIGN(pend->extra.len); pend++; } pinf++; } } nextra = nextra + (1 * sizeof(libusb_config_descriptor)) + (nif * sizeof(libusb_interface)) + (nalt * sizeof(libusb_interface_descriptor)) + (nep * sizeof(libusb_endpoint_descriptor)); nextra = N_ALIGN(nextra); pconfd = malloc(nextra); if (pconfd == NULL) { free(pconf); return (LIBUSB_ERROR_NO_MEM); } /* make sure memory is initialised */ memset(pconfd, 0, nextra); pconfd->interface = (libusb_interface *) (pconfd + 1); ifd = (libusb_interface_descriptor *) (pconfd->interface + nif); endd = (libusb_endpoint_descriptor *) (ifd + nalt); pextra = (uint8_t *)(endd + nep); /* fill in config descriptor */ pconfd->bLength = pconf->desc.bLength; pconfd->bDescriptorType = pconf->desc.bDescriptorType; pconfd->wTotalLength = pconf->desc.wTotalLength; pconfd->bNumInterfaces = pconf->desc.bNumInterfaces; pconfd->bConfigurationValue = pconf->desc.bConfigurationValue; pconfd->iConfiguration = pconf->desc.iConfiguration; pconfd->bmAttributes = pconf->desc.bmAttributes; pconfd->MaxPower = pconf->desc.bMaxPower; if (pconf->extra.len != 0) { pconfd->extra_length = pconf->extra.len; pconfd->extra = pextra; memcpy(pextra, pconf->extra.ptr, pconfd->extra_length); pextra += N_ALIGN(pconfd->extra_length); } /* setup all interface and endpoint pointers */ for (i = 0; i < nif; i++) { pconfd->interface[i].altsetting = ifd; ifd->endpoint = endd; endd += pconf->interface[i].num_endpoints; ifd++; for (j = 0; j < pconf->interface[i].num_altsetting; j++) { ifd->endpoint = endd; endd += pconf->interface[i].altsetting[j].num_endpoints; ifd++; } } /* fill in all interface and endpoint data */ for (i = 0; i < nif; i++) { pinf = &pconf->interface[i]; pconfd->interface[i].num_altsetting = pinf->num_altsetting + 1; for (j = 0; j < pconfd->interface[i].num_altsetting; j++) { if (j != 0) pinf = &pconf->interface[i].altsetting[j - 1]; ifd = &pconfd->interface[i].altsetting[j]; ifd->bLength = pinf->desc.bLength; ifd->bDescriptorType = pinf->desc.bDescriptorType; ifd->bInterfaceNumber = pinf->desc.bInterfaceNumber; ifd->bAlternateSetting = pinf->desc.bAlternateSetting; ifd->bNumEndpoints = pinf->desc.bNumEndpoints; ifd->bInterfaceClass = pinf->desc.bInterfaceClass; ifd->bInterfaceSubClass = pinf->desc.bInterfaceSubClass; ifd->bInterfaceProtocol = pinf->desc.bInterfaceProtocol; ifd->iInterface = pinf->desc.iInterface; if (pinf->extra.len != 0) { ifd->extra_length = pinf->extra.len; ifd->extra = pextra; memcpy(pextra, pinf->extra.ptr, pinf->extra.len); pextra += N_ALIGN(pinf->extra.len); } for (k = 0; k < pinf->num_endpoints; k++) { pend = &pinf->endpoints[k]; endd = &ifd->endpoint[k]; endd->bLength = pend->desc.bLength; endd->bDescriptorType = pend->desc.bDescriptorType; endd->bEndpointAddress = pend->desc.bEndpointAddress; endd->bmAttributes = pend->desc.bmAttributes; endd->wMaxPacketSize = pend->desc.wMaxPacketSize; endd->bInterval = pend->desc.bInterval; endd->bRefresh = pend->desc.bRefresh; endd->bSynchAddress = pend->desc.bSynchAddress; if (pend->extra.len != 0) { endd->extra_length = pend->extra.len; endd->extra = pextra; memcpy(pextra, pend->extra.ptr, pend->extra.len); pextra += N_ALIGN(pend->extra.len); } } } } free(pconf); *config = pconfd; return (0); /* success */ }
void usb_set_alt_interface_test(uint16_t vid, uint16_t pid) { struct libusb20_device *pdev; struct libusb20_config *config; int iter; int error; int errcnt; int n; int m; pdev = find_usb_device(vid, pid); if (pdev == NULL) { printf("USB device not found\n"); return; } printf("Starting set alternate setting test " "for VID=0x%04x PID=0x%04x\n", vid, pid); config = libusb20_dev_alloc_config(pdev, libusb20_dev_get_config_index(pdev)); if (config == NULL) { printf("Could not get configuration descriptor\n"); libusb20_dev_free(pdev); return; } iter = 0; errcnt = 0; for (n = 0; n != config->num_interface; n++) { /* detach kernel driver */ libusb20_dev_detach_kernel_driver(pdev, n); error = libusb20_dev_open(pdev, 0); if (error) printf("ERROR could not open device\n"); /* Try the alternate settings */ for (m = 0; m != config->interface[n].num_altsetting; m++) { iter++; if (libusb20_dev_set_alt_index(pdev, n, m + 1)) { printf("ERROR on interface %d alt %d\n", n, m + 1); errcnt++; } } /* Restore to default */ iter++; if (libusb20_dev_set_alt_index(pdev, n, 0)) { printf("ERROR on interface %d alt %d\n", n, 0); errcnt++; } libusb20_dev_close(pdev); } libusb20_dev_free(pdev); printf("\n" "Test summary\n" "============\n" "Interfaces tested: %d\n" "Errors: %d\n", iter, errcnt); }