Пример #1
0
/**
 * Allocates the memory for a #Camera.
 *
 * @param camera the #Camera object to initialize.
 * @return a gphoto2 error code
 *
 */
int
gp_camera_new (Camera **camera)
{
	int result;

	C_PARAMS (camera);

        C_MEM (*camera = calloc (1, sizeof (Camera)));

        (*camera)->functions = calloc (1, sizeof (CameraFunctions));
        (*camera)->pc        = calloc (1, sizeof (CameraPrivateCore));
	if (!(*camera)->functions || !(*camera)->pc) {
		result = GP_ERROR_NO_MEMORY;
		goto error;
	}

        (*camera)->pc->ref_count = 1;

	/* Create the filesystem */
	result = gp_filesystem_new (&(*camera)->fs);
	if (result < GP_OK)
		goto error;

	/* Create the port */
	result = gp_port_new (&(*camera)->port);
	if (result < GP_OK)
		goto error;

        return(GP_OK);

error:
	gp_camera_free (*camera);
	return result;
}
Пример #2
0
/**
 * @param camera a #Camera
 * @param timeout number of seconds that should pass between each call to
 * 	     \c func
 * @param func the function that should be called each \c timeout seconds
 * @return The id of the background process or a gphoto2 error code
 *
 * This function should be called by the camera driver during camera_init()
 * if the camera needs to be sent messages periodically in order to prevent
 * it from shutting down.
 *
 */
int
gp_camera_start_timeout (Camera *camera, unsigned int timeout,
			 CameraTimeoutFunc func)
{
	int id;

	C_PARAMS (camera && camera->pc);

	if (!camera->pc->timeout_start_func)
		return (GP_ERROR_NOT_SUPPORTED);

	/*
	 * We remember the id here in order to automatically remove
	 * the timeout on gp_camera_exit.
	 */
	C_MEM (camera->pc->timeout_ids =
			realloc (camera->pc->timeout_ids, sizeof (int) *
					(camera->pc->timeout_ids_len + 1)));

	id = camera->pc->timeout_start_func (camera, timeout, func,
					     camera->pc->timeout_data);
	if (id < 0)
		return (id);
	camera->pc->timeout_ids[camera->pc->timeout_ids_len] = id;
	camera->pc->timeout_ids_len++;

	return (id);
}
Пример #3
0
static int
gp_port_usbscsi_init (GPPort *port)
{
    C_MEM (port->pl = calloc (1, sizeof (GPPortPrivateLibrary)));

    port->pl->fd = -1;

    return GP_OK;
}
Пример #4
0
static int gp_port_vusb_init (GPPort *dev)
{
	gp_log(GP_LOG_DEBUG,__FUNCTION__,"()");
	C_MEM (dev->pl = calloc (1, sizeof (GPPortPrivateLibrary)));

	dev->pl->vcamera = vcamera_new(NIKON_D750);
	dev->pl->vcamera->init(dev->pl->vcamera);

	return GP_OK;
}
Пример #5
0
static int gp_libusb1_init (GPPort *port)
{
	C_MEM (port->pl = malloc (sizeof (GPPortPrivateLibrary)));
	memset (port->pl, 0, sizeof (GPPortPrivateLibrary));

	port->pl->config = port->pl->interface = port->pl->altsetting = -1;

	if (LOG_ON_LIBUSB_E (libusb_init (&port->pl->ctx))) {
		free (port->pl);
		port->pl = NULL;
		return GP_ERROR_IO;
	}
#if 0
	libusb_set_debug (port->pl->ctx, 255);
#endif
	return GP_OK;
}
Пример #6
0
/**
 * \brief Create new GPPort
 *
 * Allocate and initialize the memory for a new #GPPort.
 *
 * After you called this function, 
 * you probably want to call #gp_port_set_info in order to make the newly
 * created port functional.
 *
 * \param port Pointer the #GPPort* pointer
 * \return a gphoto2 error code
 **/
int
gp_port_new (GPPort **port)
{
	C_PARAMS (port);

        GP_LOG_D ("Creating new device...");

	C_MEM (*port = calloc (1, sizeof (GPPort)));

	(*port)->pc = calloc (1, sizeof (GPPortPrivateCore));
	if (!(*port)->pc) {
		gp_port_free (*port);
		return (GP_ERROR_NO_MEMORY);
	}

        return (GP_OK);
}
Пример #7
0
/**
 * \brief Allocate the memory for a new abilities list.
 *
 * Function to allocate the memory for a new abilities list.
 * \param list CameraAbilitiesList object to initialize
 * \return gphoto2 error code
 *
 * You would then call gp_abilities_list_load() in order to 
 * populate it.
 */
int
gp_abilities_list_new (CameraAbilitiesList **list)
{
	C_PARAMS (list);

	/*
	 * We do this here because everybody needs to call this function
	 * first before accessing a camera. Pretty ugly, but I don't know
	 * an other way without introducing a global initialization
	 * function...
	 */
	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);

	C_MEM (*list = calloc (1, sizeof (CameraAbilitiesList)));

	return (GP_OK);
}
Пример #8
0
static int gp_libusb1_init (GPPort *port)
{
	C_MEM (port->pl = malloc (sizeof (GPPortPrivateLibrary)));
	memset (port->pl, 0, sizeof (GPPortPrivateLibrary));

	port->pl->config = port->pl->interface = port->pl->altsetting = -1;

	if (LOG_ON_LIBUSB_E (libusb_init (&port->pl->ctx))) {
		free (port->pl);
		port->pl = NULL;
		return GP_ERROR_IO;
	}
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
	unlink("usblog.raw");
	port->pl->logfd = open("usblog.raw",O_CREAT|O_WRONLY,0644);
#endif
#if 0
	libusb_set_debug (port->pl->ctx, 255);
#endif
	return GP_OK;
}
Пример #9
0
static ssize_t
load_devicelist (GPPortPrivateLibrary *pl) {
	time_t	xtime;

	time(&xtime);
	if (xtime != pl->devslastchecked) {
		if (pl->nrofdevs)
			libusb_free_device_list (pl->devs, 1);
		free (pl->descs);
		pl->nrofdevs = 0;
		pl->devs = NULL;
		pl->descs = NULL;
	}
	if (!pl->nrofdevs) {
		int 	i;

		pl->nrofdevs = libusb_get_device_list (pl->ctx, &pl->devs);
		C_MEM (pl->descs = calloc (pl->nrofdevs, sizeof(pl->descs[0])));
		for (i=0;i<pl->nrofdevs;i++)
			LOG_ON_LIBUSB_E (libusb_get_device_descriptor(pl->devs[i], &pl->descs[i]));
	}
	time (&pl->devslastchecked);
	return pl->nrofdevs;
}
Пример #10
0
/**
 * \brief Append the abilities to the list.
 * \param list  CameraAbilitiesList
 * \param abilities  CameraAbilities
 * \return a gphoto2 error code
 *
 * This function is called by a camera library on camera_abilities()
 * in order to inform libgphoto2 about a supported camera model.
 *
 */
int
gp_abilities_list_append (CameraAbilitiesList *list, CameraAbilities abilities)
{
	C_PARAMS (list);

	if (list->count == list->maxcount) {
	    C_MEM (list->abilities = realloc (list->abilities,
				sizeof (CameraAbilities) * (list->maxcount + 100)));
	    list->maxcount += 100;
	}

	memcpy (&(list->abilities [list->count]), &abilities,
		sizeof (CameraAbilities));

	/* FIXME: We replace the colon by a space in the model string
	 *        This keeps backward compatibility until we have
	 *        thought of and implemented something better.
	 */
	remove_colon_from_string(list->abilities[list->count].model);

	list->count++;

	return (GP_OK);
}
Пример #11
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);
}
Пример #12
0
static int gp_port_disk_init (GPPort *dev)
{
	C_MEM (dev->pl = calloc (1, sizeof (GPPortPrivateLibrary)));

	return GP_OK;
}
Пример #13
0
/**
 * \brief Configure a port
 *
 * Makes a port functional by passing in the necessary path
 * information (from the serial:/dev/ttyS0 or similar variables).
 * After calling this function, you can access the port using for
 * example gp_port_open().
 * 
 * \param port a GPPort
 * \param info the GPPortInfo to set
 *
 * \return a gphoto2 error code
 **/
int
gp_port_set_info (GPPort *port, GPPortInfo info)
{
	int ret;

	GPPortLibraryOperations ops_func;

	C_PARAMS (port);

	free (port->pc->info.name);
	C_MEM (port->pc->info.name = strdup (info->name));
	free (port->pc->info.path);
	C_MEM (port->pc->info.path = strdup (info->path));
	port->pc->info.type = info->type;
	free (port->pc->info.library_filename);
	C_MEM (port->pc->info.library_filename = strdup (info->library_filename));

	port->type = info->type;

	/* Clean up */
	if (port->pc->ops) {
		gp_port_exit (port);
		free (port->pc->ops);
		port->pc->ops = NULL;
	}
	if (port->pc->lh) {
#if !defined(VALGRIND)
		lt_dlclose (port->pc->lh);
		lt_dlexit ();
#endif
	}

	lt_dlinit ();
	port->pc->lh = lt_dlopenext (info->library_filename);
	if (!port->pc->lh) {
		GP_LOG_E ("Could not load '%s' ('%s').", info->library_filename, lt_dlerror ());
		lt_dlexit ();
		return (GP_ERROR_LIBRARY);
	}

	/* Load the operations */
	ops_func = lt_dlsym (port->pc->lh, "gp_port_library_operations");
	if (!ops_func) {
		GP_LOG_E ("Could not find 'gp_port_library_operations' in '%s' ('%s')",
			  info->library_filename, lt_dlerror ());
		lt_dlclose (port->pc->lh);
		lt_dlexit ();
		port->pc->lh = NULL;
		return (GP_ERROR_LIBRARY);
	}
	port->pc->ops = ops_func ();
	gp_port_init (port);

	/* Initialize the settings to some default ones */
	switch (info->type) {
	case GP_PORT_SERIAL:
		port->settings.serial.speed = 0;
		port->settings.serial.bits = 8;
		port->settings.serial.parity = 0;
		port->settings.serial.stopbits = 1;
		gp_port_set_timeout (port, 500);
		break;
	case GP_PORT_USB:
		if (sizeof (port->settings.usb.port) <= strlen(info->path)) {
			GP_LOG_E ("Path is too long for static buffer '%s'.", info->path);
			return GP_ERROR_LIBRARY;
		}
		strncpy (port->settings.usb.port, info->path,
			 sizeof (port->settings.usb.port));
		port->settings.usb.inep = -1;
		port->settings.usb.outep = -1;
		port->settings.usb.config = -1;
		port->settings.usb.interface = 0;
		port->settings.usb.altsetting = -1;
		gp_port_set_timeout (port, 5000);
		break;
	case GP_PORT_USB_DISK_DIRECT:
		snprintf(port->settings.usbdiskdirect.path,
			 sizeof(port->settings.usbdiskdirect.path), "%s",
			 strchr(info->path, ':') + 1);
		break;
	case GP_PORT_USB_SCSI:
		snprintf(port->settings.usbscsi.path,
			 sizeof(port->settings.usbscsi.path), "%s",
			 strchr(info->path, ':') + 1);
		break;
	default:
		/* Nothing in here */
		break;
	}
	ret = gp_port_set_settings (port, port->settings);
	if (ret != GP_ERROR_NOT_SUPPORTED)
		CHECK_RESULT (ret);

	return GP_OK;
}