Example #1
0
static int
gp_libusb1_clear_halt_lib(GPPort *port, int ep)
{
	unsigned char internal_ep;

	C_PARAMS (port && port->pl->dh);

	switch (ep) {
	case GP_PORT_USB_ENDPOINT_IN :
		internal_ep = port->settings.usb.inep;
		break;
	case GP_PORT_USB_ENDPOINT_OUT :
		internal_ep = port->settings.usb.outep;
		break;
	case GP_PORT_USB_ENDPOINT_INT :
		internal_ep = port->settings.usb.intep;
		break;
	default:
		gp_port_set_error (port, "bad EndPoint argument 0x%x", ep);
		return GP_ERROR_BAD_PARAMETERS;
	}

	C_LIBUSB (libusb_clear_halt(port->pl->dh, internal_ep), GP_ERROR_IO_USB_CLEAR_HALT);

	return GP_OK;
}
Example #2
0
static int
gp_libusb1_msg(GPPort *port, int request, int value, int index, char *bytes, int size, int flags, int default_error)
{
	int handled = 0;
	C_PARAMS (port && port->pl->dh);

	C_LIBUSB (handled = libusb_control_transfer (port->pl->dh, flags, request, value, index,
			(unsigned char*)bytes, size, port->timeout),
		  default_error);

	return handled;
}
Example #3
0
static int
gp_libusb1_reset(GPPort *port)
{
	C_PARAMS (port && port->pl->dh);

	/* earlier libusb 1 versions get crashes otherwise */
	_close_async_interrupts(port);

	C_LIBUSB (libusb_reset_device (port->pl->dh), GP_ERROR_IO);

	return GP_OK;
}
Example #4
0
static int
gp_libusb1_read(GPPort *port, char *bytes, int size)
{
	int curread;

	C_PARAMS (port && port->pl->dh);

	C_LIBUSB (libusb_bulk_transfer (port->pl->dh, port->settings.usb.inep,
			(unsigned char*)bytes, size, &curread, port->timeout),
		  GP_ERROR_IO_READ );

        return curread;
}
Example #5
0
static int
gp_libusb1_write (GPPort *port, const char *bytes, int size)
{
        int curwritten;

	C_PARAMS (port && port->pl->dh);

	C_LIBUSB (libusb_bulk_transfer (port->pl->dh, port->settings.usb.outep,
                           (unsigned char*)bytes, size, &curwritten, port->timeout),
                  GP_ERROR_IO_WRITE);

        return curwritten;
}
Example #6
0
static int
gp_libusb1_read(GPPort *port, char *bytes, int size)
{
	int curread;

	C_PARAMS (port && port->pl->dh);

	C_LIBUSB (libusb_bulk_transfer (port->pl->dh, port->settings.usb.inep,
			(unsigned char*)bytes, size, &curread, port->timeout),
		  GP_ERROR_IO_READ );

#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
	write(port->pl->logfd, bytes, curread);
#endif
        return curread;
}
Example #7
0
/*
 * This function applys changes to the device.
 *
 * New settings are in port->settings_pending and the old ones
 * are in port->settings. Compare them first and only call
 * usb_set_configuration() and usb_set_altinterface() if needed
 * since some USB devices does not like it if this is done
 * more than necessary (Canon Digital IXUS 300 for one).
 *
 */
static int
gp_libusb1_update (GPPort *port)
{
	int ifacereleased = FALSE, changedone = FALSE;

	C_PARAMS (port && port->pl && port->pl->ctx);

	GP_LOG_D ("(old int=%d, conf=%d, alt=%d) port %s, (new int=%d, conf=%d, alt=%d) port %s",
		port->settings.usb.interface,
		port->settings.usb.config,
		port->settings.usb.altsetting,
		port->settings.usb.port,
		port->settings_pending.usb.interface,
		port->settings_pending.usb.config,
		port->settings_pending.usb.altsetting,
		port->settings_pending.usb.port
	);

/* do not overwrite it ... we need to set it.
	if (port->pl->interface == -1) port->pl->interface = port->settings.usb.interface;
	if (port->pl->config == -1) port->pl->config = port->settings.usb.config;
	if (port->pl->altsetting == -1) port->pl->altsetting = port->settings.usb.altsetting;
*/

	/* The portname can also be changed with the device still fully closed. */
	memcpy(&port->settings.usb.port, &port->settings_pending.usb.port,
		sizeof(port->settings.usb.port));

	if (!port->pl->dh) {
		GP_LOG_D("lowlevel libusb1 port not yet opened, no need for libusb changes");
		return GP_OK; /* the port might not be opened, yet. that is ok */
	}

	memcpy(&port->settings.usb, &port->settings_pending.usb,
		sizeof(port->settings.usb));

	/* The interface changed. release the old, claim the new ... */
	if (port->settings.usb.interface != port->pl->interface) {
		GP_LOG_D ("changing interface %d -> %d", port->pl->interface, port->settings.usb.interface);
		if (LOG_ON_LIBUSB_E (libusb_release_interface (port->pl->dh, port->pl->interface))) {
			/* Not a hard error for now. -Marcus */
		} else {
			GP_LOG_D ("claiming interface %d", port->settings.usb.interface);
			C_LIBUSB (libusb_claim_interface (port->pl->dh, port->settings.usb.interface),
				  GP_ERROR_IO_USB_CLAIM);
			port->pl->interface = port->settings.usb.interface;
		}
		changedone = TRUE;
	}
	if (port->settings.usb.config != port->pl->config) {
		GP_LOG_D ("changing config %d -> %d", port->pl->config, port->settings.usb.config);
		/* This can only be changed with the interface released. 
		 * This is a hard requirement since 2.6.12.
		 */
		if (LOG_ON_LIBUSB_E (libusb_release_interface (port->pl->dh, port->settings.usb.interface))) {
			ifacereleased = FALSE;
		} else {
			ifacereleased = TRUE;
		}
		if (LOG_ON_LIBUSB_E (libusb_set_configuration(port->pl->dh, port->settings.usb.config))) {
#if 0 /* setting the configuration failure is not fatal */
			int saved_errno = errno;
			gp_port_set_error (port,
					   _("Could not set config %d/%d (%s)"),
					   port->settings.usb.interface,
					   port->settings.usb.config,
					   strerror(saved_errno));
			return GP_ERROR_IO_UPDATE;	
#endif
			GP_LOG_E ("setting configuration from %d to %d failed, but continuing...", port->pl->config, port->settings.usb.config);
		}

		GP_LOG_D ("Changed usb.config from %d to %d", port->pl->config, port->settings.usb.config);

		if (ifacereleased) {
			GP_LOG_D ("claiming interface %d", port->settings.usb.interface);
			LOG_ON_LIBUSB_E (libusb_claim_interface (port->pl->dh, port->settings.usb.interface));
		}
		/*
		 * Copy at once if something else fails so that this
		 * does not get re-applied
		 */
		port->pl->config = port->settings.usb.config;
		changedone = TRUE;
	}

	/* This can be changed with interface claimed. (And I think it must be claimed.) */
	if (port->settings.usb.altsetting != port->pl->altsetting) {
		if (LOG_ON_LIBUSB_E (libusb_set_interface_alt_setting (port->pl->dh,
					port->settings.usb.interface, port->settings.usb.altsetting))) {
			int saved_errno = errno;
			gp_port_set_error (port,
					   _("Could not set altsetting from %d "
					     "to %d (%s)"),
					   port->pl->altsetting,
					   port->settings.usb.altsetting,
					   strerror(saved_errno));
			return GP_ERROR_IO_UPDATE;
		}

		GP_LOG_D ("Changed usb.altsetting from %d to %d", port->pl->altsetting, port->settings.usb.altsetting);
		port->pl->altsetting = port->settings.usb.altsetting;
		changedone = TRUE;
	}

	/* requeue the interrupts */
	if (changedone)
		gp_libusb1_queue_interrupt_urbs (port);
	return GP_OK;
}
Example #8
0
static int
gp_libusb1_open (GPPort *port)
{
	int ret;

	GP_LOG_D ("()");
	C_PARAMS (port);

	if (!port->pl->d) {
		gp_libusb1_find_path_lib(port);
		C_PARAMS (port->pl->d);
	}

	C_LIBUSB (libusb_open (port->pl->d, &port->pl->dh), GP_ERROR_IO);
	if (!port->pl->dh) {
		int saved_errno = errno;
		gp_port_set_error (port, _("Could not open USB device (%s)."),
				   strerror(saved_errno));
		return GP_ERROR_IO;
	}
	ret = libusb_kernel_driver_active (port->pl->dh, port->settings.usb.interface);

#if 0
	if (strstr(name,"usbfs") || strstr(name,"storage")) {
		/* other gphoto instance most likely */
		gp_port_set_error (port, _("Camera is already in use."));
		return GP_ERROR_IO_LOCK;
	}
#endif

	switch (ret) {
	case 1: GP_LOG_D ("Device has a kernel driver attached (%d), detaching it now.", ret);
		ret = libusb_detach_kernel_driver (port->pl->dh, port->settings.usb.interface);
		if (ret < 0)
			gp_port_set_error (port, _("Could not detach kernel driver of camera device."));
		else
			port->pl->detached = 1;
	case 0:	/* not detached */
		break;
	default:
		gp_port_set_error (port, _("Could not query kernel driver of device."));
		break;
	}

	GP_LOG_D ("claiming interface %d", port->settings.usb.interface);
	if (LOG_ON_LIBUSB_E (libusb_claim_interface (port->pl->dh, port->settings.usb.interface))) {
		int saved_errno = errno;
		gp_port_set_error (port, _("Could not claim interface %d (%s). "
					   "Make sure no other program (%s) "
					   "or kernel module (such as %s) "
					   "is using the device and you have "
					   "read/write access to the device."),
				   port->settings.usb.interface,
				   strerror(saved_errno),
#ifdef __linux__
				   "gvfs-gphoto2-volume-monitor",
#else
#if defined(__APPLE__)
				   _("MacOS PTPCamera service"),
#else
				   _("unknown libgphoto2 using program"),
#endif
#endif
				   "sdc2xx, stv680, spca50x");
		return GP_ERROR_IO_USB_CLAIM;
	}

	gp_libusb1_queue_interrupt_urbs (port);

	return GP_OK;
}
Example #9
0
int
gp_port_library_list (GPPortInfoList *list)
{
	GPPortInfo	info;
	int		nrofdevices = 0;
	int		d, i, i1, i2, unknownint;
	libusb_context	*ctx;
	libusb_device	**devs = NULL;
	int		nrofdevs = 0;
	struct libusb_device_descriptor	*descs;

	C_LIBUSB (libusb_init (&ctx), GP_ERROR_IO);

	/* TODO: make sure libusb_exit gets called in all error paths inside this function */

	/* generic matcher. This will catch passed XXX,YYY entries for instance. */
	C_GP (gp_port_info_new (&info));
	gp_port_info_set_type (info, GP_PORT_USB);
	gp_port_info_set_name (info, "");
	gp_port_info_set_path (info, "^usb:");
	C_GP (gp_port_info_list_append (list, info));

	nrofdevs = libusb_get_device_list (ctx, &devs);
	C_MEM (descs = calloc (nrofdevs, sizeof(descs[0])));
	for (i=0;i<nrofdevs;i++)
		LOG_ON_LIBUSB_E (libusb_get_device_descriptor(devs[i], &descs[i]));

	for (d = 0; d < nrofdevs; d++) {
		/* Devices which are definitely not cameras. */
		if (	(descs[d].bDeviceClass == LIBUSB_CLASS_HUB)		||
			(descs[d].bDeviceClass == LIBUSB_CLASS_HID)		||
			(descs[d].bDeviceClass == LIBUSB_CLASS_PRINTER)	||
			(descs[d].bDeviceClass == LIBUSB_CLASS_COMM)	||
			(descs[d].bDeviceClass == 0xe0)	/* wireless / bluetooth */
		)
			continue;
		/* excepts HUBs, usually the interfaces have the classes, not
		 * the device */
		unknownint = 0;
		for (i = 0; i < descs[d].bNumConfigurations; i++) {
			struct libusb_config_descriptor *config;

			if (LOG_ON_LIBUSB_E (libusb_get_config_descriptor (devs[d], i, &config))) {
				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 < nrofdevs; d++) {
		char path[200];

		/* Devices which are definitely not cameras. */
		if (	(descs[d].bDeviceClass == LIBUSB_CLASS_HUB)		||
			(descs[d].bDeviceClass == LIBUSB_CLASS_HID)		||
			(descs[d].bDeviceClass == LIBUSB_CLASS_PRINTER)	||
			(descs[d].bDeviceClass == LIBUSB_CLASS_COMM)
		)
			continue;
		/* excepts HUBs, usually the interfaces have the classes, not
		 * the device */
		unknownint = 0;
		for (i = 0; i < descs[d].bNumConfigurations; i++) {
			struct libusb_config_descriptor *config;

			if (LOG_ON_LIBUSB_E (libusb_get_config_descriptor (devs[d], i, &config))) {
				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.
		 */ 
		C_GP (gp_port_info_new (&info));
		gp_port_info_set_type (info, GP_PORT_USB);
		gp_port_info_set_name (info, "Universal Serial Bus");
		snprintf (path,sizeof(path), "usb:%03d,%03d",
			libusb_get_bus_number (devs[d]),
			libusb_get_device_address (devs[d])
		);
		gp_port_info_set_path (info, path);
		C_GP (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) {
		C_GP (gp_port_info_new (&info));
		gp_port_info_set_type (info, GP_PORT_USB);
		gp_port_info_set_name (info, "Universal Serial Bus");
		gp_port_info_set_path (info, "usb:");
		C_GP (gp_port_info_list_append (list, info));
	}
	libusb_free_device_list (devs, 1);
	libusb_exit (ctx); /* should free all stuff above */
	free (descs);
	return (GP_OK);
}