struct xusb *xusb_open_one(const struct xusb_spec *specs, int numspecs, xusb_filter_t filterfunc, void *data) { struct xlist_node *xusb_list; struct xlist_node *curr; int num; struct xusb *xusb = NULL; xusb_list = xusb_find_byproduct(specs, numspecs, filterfunc, data); num = xlist_length(xusb_list); DBG("total %d devices\n", num); switch (num) { case 0: ERR("No matching device.\n"); break; case 1: curr = xlist_shift(xusb_list); xusb = curr->data; xlist_destroy(curr, NULL); xlist_destroy(xusb_list, NULL); if (!xusb_claim_interface(xusb)) { xusb_destroy(xusb); return NULL; } xusb_showinfo(xusb); break; default: ERR("Too many devices (%d). Aborting.\n", num); break; } return xusb; }
static int run_spec(int i, xusb_filter_t filter, char *devpath, int timeout) { const struct xusb_spec *s = &known_devices[i].spec; int interface_num = known_devices[i].interface_num; struct xlist_node *xlist; struct xlist_node *curr; struct xusb_device *xusb_device; int success = 1; if (!s->name) return 0; xlist = xusb_find_byproduct(s, 1, filter, devpath); if (!xlist_length(xlist)) return 1; INFO("total %zd devices of type %s\n", xlist_length(xlist), s->name); for (curr = xlist_shift(xlist); curr; curr = xlist_shift(xlist)) { struct xusb_iface *xusb_iface; int ret; xusb_device = curr->data; xusb_showinfo(xusb_device); INFO("Testing interface %d\n", interface_num); ret = xusb_claim(xusb_device, interface_num, &xusb_iface); if (ret == 0) { ret = test_device(xusb_iface, timeout); if (ret < 0) success = 0; } xusb_destroy(xusb_device); } xlist_destroy(xlist, xusb_destructor); return success; }
struct xlist_node *xusb_find_byproduct(const struct xusb_spec *specs, int numspecs, xusb_filter_t filterfunc, void *data) { struct xlist_node *xlist; struct usb_bus *bus; struct usb_device *dev; DBG("specs(%d)\n", numspecs); xlist = xlist_new(NULL); if (!xlist) { ERR("Failed allocation new xlist"); goto fail_xlist; } xusb_init(); for (bus = usb_get_busses(); bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { struct usb_device_descriptor *dev_desc; struct xlist_node *item; int i; dev_desc = &dev->descriptor; assert(dev_desc); DBG("usb:%s/%s: ID=%04X:%04X\n", dev->bus->dirname, dev->filename, dev_desc->idVendor, dev_desc->idProduct); for (i = 0; i < numspecs; i++) { struct xusb *xusb; const struct xusb_spec *sp = &specs[i]; if (!match_interface(dev, sp)) continue; xusb = xusb_new(dev, sp); if (!xusb) { ERR("xusb allocation failed\n"); goto fail_malloc; } if (filterfunc && !filterfunc(xusb, data)) { xusb_destroy(xusb); continue; } item = xlist_new(xusb); xlist_append_item(xlist, item); break; } } } xusb_list_dump(xlist); return xlist; fail_malloc: xlist_destroy(xlist, NULL); fail_xlist: return NULL; }
static struct xusb *xusb_new(struct usb_device *dev, const struct xusb_spec *spec) { struct usb_device_descriptor *dev_desc; struct usb_config_descriptor *config_desc; struct usb_interface *interface; struct usb_interface_descriptor *iface_desc; struct usb_endpoint_descriptor *endpoint; size_t max_packet_size; int i; struct xusb *xusb = NULL; /* * Get information from the usb_device */ if((dev_desc = &dev->descriptor) == NULL) { ERR("usb device without a device descriptor\n"); goto fail; } if((config_desc = dev->config) == NULL) { ERR("usb device without a configuration descriptor\n"); goto fail; } interface = &config_desc->interface[spec->my_interface_num]; iface_desc = interface->altsetting; endpoint = iface_desc->endpoint; /* Calculate max packet size */ max_packet_size = PACKET_SIZE; for(i = 0; i < iface_desc->bNumEndpoints; i++, endpoint++) { DBG("Validating endpoint @ %d (interface %d)\n", i, spec->my_interface_num); if(endpoint->bEndpointAddress == spec->my_ep_out || endpoint->bEndpointAddress == spec->my_ep_in) { if(endpoint->wMaxPacketSize > PACKET_SIZE) { ERR("Endpoint #%d wMaxPacketSize too large (%d)\n", i, endpoint->wMaxPacketSize); goto fail; } if(endpoint->wMaxPacketSize < max_packet_size) { max_packet_size = endpoint->wMaxPacketSize; } } } /* Fill xusb */ if((xusb = malloc(sizeof(*xusb))) == NULL) { ERR("Out of memory"); goto fail; } memset(xusb, 0, sizeof(*xusb)); xusb->dev = dev; xusb->spec = spec; sscanf(dev->bus->dirname, "%d", &xusb->bus_num); sscanf(dev->filename, "%d", &xusb->device_num); snprintf(xusb->devpath_tail, PATH_MAX, "%03d/%03d", xusb->bus_num, xusb->device_num); xusb->interface_num = spec->my_interface_num; xusb->ep_out = spec->my_ep_out; xusb->ep_in = spec->my_ep_in; xusb->packet_size = max_packet_size; xusb->is_usb2 = (max_packet_size == 512); if (! xusb_open(xusb)) { ERR("Failed opening device: %04X:%04X - %s\n", dev_desc->idVendor, dev_desc->idProduct, xusb->devpath_tail); goto fail; } DBG("%04X:%04X - %s\n", dev_desc->idVendor, dev_desc->idProduct, xusb->devpath_tail); return xusb; fail: xusb_destroy(xusb); return NULL; }
static void xusb_destructor(void *data) { struct xusb_device *xusb_device = data; xusb_destroy(xusb_device); }