static int gp_libusb1_find_device_lib(GPPort *port, int idvendor, int idproduct) { char *s; int d, busnr = 0, devnr = 0; GPPortPrivateLibrary *pl; C_PARAMS (port); pl = port->pl; s = strchr (port->settings.usb.port,':'); if (s && (s[1] != '\0')) { /* usb:%d,%d */ if (sscanf (s+1, "%d,%d", &busnr, &devnr) != 2) { devnr = 0; sscanf (s+1, "%d", &busnr); } } /* * 0x0000 idvendor is not valid. * 0x0000 idproduct is ok. * Should the USB layer report that ? I don't know. * Better to check here. */ if (!idvendor) { gp_port_set_error (port, _("The supplied vendor or product " "id (0x%x,0x%x) is not valid."), idvendor, idproduct); return GP_ERROR_BAD_PARAMETERS; } pl->nrofdevs = load_devicelist (port->pl); for (d = 0; d < pl->nrofdevs; d++) { struct libusb_config_descriptor *confdesc; int config = -1, interface = -1, altsetting = -1; if ((pl->descs[d].idVendor != idvendor) || (pl->descs[d].idProduct != idproduct)) continue; if (busnr && (busnr != libusb_get_bus_number (pl->devs[d]))) continue; if (devnr && (devnr != libusb_get_device_address (pl->devs[d]))) continue; port->pl->d = pl->devs[d]; GP_LOG_D ("Looking for USB device (vendor 0x%x, product 0x%x)... found.", idvendor, idproduct); /* Use the first config, interface and altsetting we find */ gp_libusb1_find_first_altsetting(pl->devs[d], &config, &interface, &altsetting); if (LOG_ON_LIBUSB_E (libusb_get_config_descriptor (pl->devs[d], config, &confdesc))) continue; /* Set the defaults */ if (confdesc->interface[interface].altsetting[altsetting].bInterfaceClass == LIBUSB_CLASS_MASS_STORAGE) { GP_LOG_D ("USB device (vendor 0x%x, product 0x%x) is a mass" " storage device, and might not function with gphoto2." " Reference: %s", idvendor, idproduct, URL_USB_MASSSTORAGE); } port->settings.usb.config = confdesc->bConfigurationValue; port->settings.usb.interface = confdesc->interface[interface].altsetting[altsetting].bInterfaceNumber; port->settings.usb.altsetting = confdesc->interface[interface].altsetting[altsetting].bAlternateSetting; port->settings.usb.inep = gp_libusb1_find_ep(pl->devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_IN, LIBUSB_TRANSFER_TYPE_BULK); port->settings.usb.outep = gp_libusb1_find_ep(pl->devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_OUT, LIBUSB_TRANSFER_TYPE_BULK); port->settings.usb.intep = gp_libusb1_find_ep(pl->devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_IN, LIBUSB_TRANSFER_TYPE_INTERRUPT); port->settings.usb.maxpacketsize = libusb_get_max_packet_size (pl->devs[d], port->settings.usb.inep); GP_LOG_D ("Detected defaults: config %d, interface %d, altsetting %d, " "inep %02x, outep %02x, intep %02x, class %02x, subclass %02x", port->settings.usb.config, port->settings.usb.interface, port->settings.usb.altsetting, port->settings.usb.inep, port->settings.usb.outep, port->settings.usb.intep, confdesc->interface[interface].altsetting[altsetting].bInterfaceClass, confdesc->interface[interface].altsetting[altsetting].bInterfaceSubClass ); libusb_free_config_descriptor (confdesc); return GP_OK; } #if 0 gp_port_set_error (port, _("Could not find USB device " "(vendor 0x%x, product 0x%x). Make sure this device " "is connected to the computer."), idvendor, idproduct); #endif return GP_ERROR_IO_USB_FIND; }
static int gp_libusb1_find_path_lib(GPPort *port) { char *s; int d, busnr = 0, devnr = 0; GPPortPrivateLibrary *pl; C_PARAMS (port); pl = port->pl; s = strchr (port->settings.usb.port,':'); C_PARAMS (s && (s[1] != '\0')); C_PARAMS (sscanf (s+1, "%d,%d", &busnr, &devnr) == 2); /* usb:%d,%d */ pl->nrofdevs = load_devicelist (port->pl); for (d = 0; d < pl->nrofdevs; d++) { struct libusb_config_descriptor *confdesc; int config = -1, interface = -1, altsetting = -1; if (busnr != libusb_get_bus_number (pl->devs[d])) continue; if (devnr != libusb_get_device_address (pl->devs[d])) continue; port->pl->d = pl->devs[d]; GP_LOG_D ("Found path %s", port->settings.usb.port); /* Use the first config, interface and altsetting we find */ gp_libusb1_find_first_altsetting(pl->devs[d], &config, &interface, &altsetting); if (LOG_ON_LIBUSB_E (libusb_get_config_descriptor (pl->devs[d], config, &confdesc))) continue; /* Set the defaults */ port->settings.usb.config = confdesc->bConfigurationValue; port->settings.usb.interface = confdesc->interface[interface].altsetting[altsetting].bInterfaceNumber; port->settings.usb.altsetting = confdesc->interface[interface].altsetting[altsetting].bAlternateSetting; port->settings.usb.inep = gp_libusb1_find_ep(pl->devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_IN, LIBUSB_TRANSFER_TYPE_BULK); port->settings.usb.outep = gp_libusb1_find_ep(pl->devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_OUT, LIBUSB_TRANSFER_TYPE_BULK); port->settings.usb.intep = gp_libusb1_find_ep(pl->devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_IN, LIBUSB_TRANSFER_TYPE_INTERRUPT); port->settings.usb.maxpacketsize = libusb_get_max_packet_size (pl->devs[d], port->settings.usb.inep); GP_LOG_D ("Detected defaults: config %d, interface %d, altsetting %d, " "inep %02x, outep %02x, intep %02x, class %02x, subclass %02x", port->settings.usb.config, port->settings.usb.interface, port->settings.usb.altsetting, port->settings.usb.inep, port->settings.usb.outep, port->settings.usb.intep, confdesc->interface[interface].altsetting[altsetting].bInterfaceClass, confdesc->interface[interface].altsetting[altsetting].bInterfaceSubClass ); libusb_free_config_descriptor (confdesc); return GP_OK; } #if 0 gp_port_set_error (port, _("Could not find USB device " "(vendor 0x%x, product 0x%x). Make sure this device " "is connected to the computer."), idvendor, idproduct); #endif return GP_ERROR_IO_USB_FIND; }
int gp_port_library_list (GPPortInfoList *list) { GPPortInfo info; int nrofdevices = 0; int d, i, i1, i2, unknownint; /* generic matcher. This will catch passed XXX,YYY entries for instance. */ info.type = GP_PORT_USB; strcpy (info.name, ""); strcpy (info.path, "^usb:"); CHECK (gp_port_info_list_append (list, info)); libusb_init (NULL); gp_nrofdevs = load_devicelist (NULL); for (d = 0; d < gp_nrofdevs; d++) { /* Devices which are definitely not cameras. */ if ( (gp_descs[d].bDeviceClass == LIBUSB_CLASS_HUB) || (gp_descs[d].bDeviceClass == LIBUSB_CLASS_HID) || (gp_descs[d].bDeviceClass == LIBUSB_CLASS_PRINTER) || (gp_descs[d].bDeviceClass == LIBUSB_CLASS_COMM) || (gp_descs[d].bDeviceClass == 0xe0) /* wireless / bluetooth */ ) continue; /* excepts HUBs, usually the interfaces have the classes, not * the device */ unknownint = 0; for (i = 0; i < gp_descs[d].bNumConfigurations; i++) { struct libusb_config_descriptor *config; int ret; ret = libusb_get_config_descriptor (gp_devs[d], i, &config); if (ret) { unknownint++; continue; } for (i1 = 0; i1 < config->bNumInterfaces; i1++) for (i2 = 0; i2 < config->interface[i1].num_altsetting; i2++) { const struct libusb_interface_descriptor *intf = &config->interface[i1].altsetting[i2]; if ( (intf->bInterfaceClass == LIBUSB_CLASS_HID) || (intf->bInterfaceClass == LIBUSB_CLASS_PRINTER) || (intf->bInterfaceClass == LIBUSB_CLASS_COMM) || (intf->bInterfaceClass == 0xe0) /* wireless/bluetooth*/ ) continue; unknownint++; } libusb_free_config_descriptor (config); } /* when we find only hids, printer or comm ifaces ... skip this */ if (!unknownint) continue; /* Note: We do not skip USB storage. Some devices can support both, * and the Ricoh erronously reports it. */ nrofdevices++; } #if 0 /* If we already added usb:, and have 0 or 1 devices we have nothing to do. * This should be the standard use case. */ /* We never want to return just "usb:" ... also return "usb:XXX,YYY", and * let upper layers filter out the usb: */ if (nrofdevices <= 1) return (GP_OK); #endif /* Redo the same bus/device walk, but now add the ports with usb:x,y notation, * so we can address all USB devices. */ for (d = 0; d < gp_nrofdevs; d++) { /* Devices which are definitely not cameras. */ if ( (gp_descs[d].bDeviceClass == LIBUSB_CLASS_HUB) || (gp_descs[d].bDeviceClass == LIBUSB_CLASS_HID) || (gp_descs[d].bDeviceClass == LIBUSB_CLASS_PRINTER) || (gp_descs[d].bDeviceClass == LIBUSB_CLASS_COMM) ) continue; /* excepts HUBs, usually the interfaces have the classes, not * the device */ unknownint = 0; for (i = 0; i < gp_descs[d].bNumConfigurations; i++) { struct libusb_config_descriptor *config; int ret; ret = libusb_get_config_descriptor (gp_devs[d], i, &config); if (ret) { gp_log (GP_LOG_ERROR, "libusb1", "libusb_get_config_descriptor(%d) returned %d", d, ret); unknownint++; continue; } for (i1 = 0; i1 < config->bNumInterfaces; i1++) for (i2 = 0; i2 < config->interface[i1].num_altsetting; i2++) { const struct libusb_interface_descriptor *intf = &config->interface[i1].altsetting[i2]; if ( (intf->bInterfaceClass == LIBUSB_CLASS_HID) || (intf->bInterfaceClass == LIBUSB_CLASS_PRINTER) || (intf->bInterfaceClass == LIBUSB_CLASS_COMM)) continue; unknownint++; } libusb_free_config_descriptor (config); } /* when we find only hids, printer or comm ifaces ... skip this */ if (!unknownint) continue; /* Note: We do not skip USB storage. Some devices can support both, * and the Ricoh erronously reports it. */ info.type = GP_PORT_USB; strcpy (info.name, "Universal Serial Bus"); snprintf (info.path,sizeof(info.path), "usb:%03d,%03d", libusb_get_bus_number (gp_devs[d]), libusb_get_device_address (gp_devs[d]) ); CHECK (gp_port_info_list_append (list, info)); } /* This will only be added if no other device was ever added. * Users doing "usb:" usage will enter the regular expression matcher case. */ if (nrofdevices == 0) { info.type = GP_PORT_USB; strcpy (info.name, "Universal Serial Bus"); strcpy (info.path, "usb:"); CHECK (gp_port_info_list_append (list, info)); } libusb_exit (NULL); return (GP_OK); }