/**
 * \brief Lookup a specific path in the list
 *
 * \param list a #GPPortInfoList
 * \param path a path
 *
 * Looks for an entry in the list with the supplied path. If no exact match
 * can be found, a regex search will be performed in the hope some driver
 * claimed ports like "serial:*".
 *
 * \return The index of the entry or a gphoto2 error code
 **/
int
gp_port_info_list_lookup_path (GPPortInfoList *list, const char *path)
{
	int i, result, generic;
	regex_t pattern;
#ifdef HAVE_GNU_REGEX
	const char *rv;
#else
	regmatch_t match;
#endif

	CHECK_NULL (list && path);

	gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list", ngettext(
		"Looking for path '%s' (%i entry available)...",
		"Looking for path '%s' (%i entries available)...",
		list->count
	), path, list->count);

	/* Exact match? */
	for (generic = i = 0; i < list->count; i++)
		if (!strlen (list->info[i].name))
			generic++;
		else if (!strcmp (list->info[i].path, path))
			return (i - generic);

	/* Regex match? */
	gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list",
		_("Starting regex search for '%s'..."), path);
	for (i = 0; i < list->count; i++) {
		GPPortInfo newinfo;

		if (strlen (list->info[i].name))
			continue;

		gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list",
			_("Trying '%s'..."), list->info[i].path);

		/* Compile the pattern */
#ifdef HAVE_GNU_REGEX
		memset (&pattern, 0, sizeof (pattern));
		rv = re_compile_pattern (list->info[i].path,
					 strlen (list->info[i].path), &pattern);
		if (rv) {
			gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list",
				"%s", rv);
			continue;
		}
#else
		result = regcomp (&pattern, list->info[i].path, REG_ICASE);
		if (result) {
			char buf[1024];
			if (regerror (result, &pattern, buf, sizeof (buf)))
				gp_log (GP_LOG_ERROR, "gphoto2-port-info-list",
					"%s", buf);
			else
				gp_log (GP_LOG_ERROR, "gphoto2-port-info-list",
					_("regcomp failed"));
			return (GP_ERROR_UNKNOWN_PORT);
		}
#endif

		/* Try to match */
#ifdef HAVE_GNU_REGEX
		result = re_match (&pattern, path, strlen (path), 0, NULL);
		regfree (&pattern);
		if (result < 0) {
			gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list",
				_("re_match failed (%i)"), result);
			continue;
		}
#else
		result = regexec (&pattern, path, 1, &match, 0);
		regfree (&pattern);
		if (result) {
			gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list",
				_("regexec failed"));
			continue;
		}
#endif
		memcpy (&newinfo, &list->info[i], sizeof(newinfo));
		strncpy (newinfo.path, path, sizeof (newinfo.path));
		strncpy (newinfo.name, _("Generic Port"), sizeof (newinfo.name));
		CR (result = gp_port_info_list_append (list, newinfo));
		return result;
	}

	return (GP_ERROR_UNKNOWN_PORT);
}
Пример #2
0
static int
put_file_func (CameraFilesystem *fs, const char *folder, const char *filename, CameraFile *file,
	       void *data, GPContext *context)
{
	Camera *camera = data;

	/*
	 * Upload the file to the camera. Use gp_file_get_data_and_size etc.
	 */
	int result = -EPROTO;
	time_t startTime = time(NULL);
	enum {
		START,
		DATA,
		END,
		FINISHED
	} state;
	int src = -1;
	int r;
	int update = 0;
	struct stat srcStat;
	__u64 fileSize;
	__u64 byteCount = 0;
	const char *filename;
	char *path;
	struct tf_packet reply;

	if(0 != fstat(src, &srcStat))
	{
		gp_log (GP_LOG_ERROR, "topfield", "ERROR: Can not examine source file: %s\n",
			strerror(errno));
		result = errno;
		goto out;
	}

	fileSize = srcStat.st_size;
	if(fileSize == 0)
	{
		gp_log (GP_LOG_ERROR, "topfield", "ERROR: Source file is empty - not transfering.\n");
		result = -ENODATA;
		goto out;
	}

	path = get_path (camera, folder, filename);
	r = send_cmd_hdd_file_send(camera, PUT, path, context);
	if(r < 0)
		goto out;

	state = START;
	while(0 < get_tf_packet(camera, &reply, context)) {
		update = (update + 1) % 16;
		switch (get_u32(&reply.cmd)) {
		case SUCCESS:
			switch (state) {
			case START: {
				/* Send start */
				struct typefile *tf = (struct typefile *) packet.data;

				put_u16(&packet.length, PACKET_HEAD_SIZE + 114);
				put_u32(&packet.cmd, DATA_HDD_FILE_START);
				time_to_tfdt(srcStat.st_mtime, &tf->stamp);
				tf->filetype = 2;
				put_u64(&tf->size, srcStat.st_size);
				strncpy((char *) tf->name, path, 94);
				tf->name[94] = '\0';
				tf->unused = 0;
				tf->attrib = 0;
				gp_log (GP_LOG_DEBUG, "topfield", "%s: DATA_HDD_FILE_START\n", __func__);
				r = send_tf_packet(camera, &packet, context);
				if(r < 0)
				{
					gp_log (GP_LOG_ERROR, "topfield", "ERROR: Incomplete send.\n");
					goto out;
				}
				state = DATA;
				break;
			}

			case DATA: {
				int payloadSize = sizeof(packet.data) - 9;
				ssize_t w = read(src, &packet.data[8], payloadSize);

				/* Detect a Topfield protcol bug and prevent the sending of packets
				   that are a multiple of 512 bytes. */
				if((w > 4) && (((((PACKET_HEAD_SIZE + 8 + w) + 1) & ~1) % 0x200) == 0)) {
					lseek(src, -4, SEEK_CUR);
					w -= 4;
					payloadSize -= 4;
				}

				put_u16(&packet.length, PACKET_HEAD_SIZE + 8 + w);
				put_u32(&packet.cmd, DATA_HDD_FILE_DATA);
				put_u64(packet.data, byteCount);
				byteCount += w;

				/* Detect EOF and transition to END */
				if((w < 0) || (byteCount >= fileSize)) {
					state = END;
				}

				if(w > 0) {
					gp_log (GP_LOG_DEBUG, "topfield", "%s: DATA_HDD_FILE_DATA\n", __func__);
					r = send_tf_packet(camera, &packet, context);
					if(r < w) {
						gp_log (GP_LOG_ERROR, "topfield", "ERROR: Incomplete send.\n");
						goto out;
					}
				}

				if(!update && !quiet) {
					progressStats(fileSize, byteCount, startTime);
				}
				break;
			}

			case END:
				/* Send end */
				put_u16(&packet.length, PACKET_HEAD_SIZE);
				put_u32(&packet.cmd, DATA_HDD_FILE_END);
				gp_log (GP_LOG_DEBUG, "topfield", "%s: DATA_HDD_FILE_END\n", __func__);
				r = send_tf_packet(camera, &packet, context);
				if(r < 0) {
					gp_log (GP_LOG_ERROR, "topfield", "ERROR: Incomplete send.\n");
					goto out;
				}
				state = FINISHED;
				break;

			case FINISHED:
				result = 0;
				goto out;
				break;
			}
			break;

		case FAIL:
			gp_log (GP_LOG_ERROR, "topfield", "ERROR: Device reports %s\n", decode_error(&reply));
			goto out;
			break;

		default:
			gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unhandled packet (%d)\n", get_u32(&reply.cmd));
			break;
		}
	}
	finalStats(byteCount, startTime);
out:
	close(src);
	return result;
}
static int
foreach_func (const char *filename, lt_ptr data)
{
	GPPortInfoList *list = data;
	lt_dlhandle lh;
	GPPortLibraryType lib_type;
	GPPortLibraryList lib_list;
	GPPortType type;
	unsigned int j, old_size = list->count;
	int result;

	gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list",
		_("Called for filename '%s'."), filename );

	lh = lt_dlopenext (filename);
	if (!lh) {
		gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list",
			_("Could not load '%s': '%s'."), filename, lt_dlerror ());
		return (0);
	}

	lib_type = lt_dlsym (lh, "gp_port_library_type");
	lib_list = lt_dlsym (lh, "gp_port_library_list");
	if (!lib_type || !lib_list) {
		gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list",
			_("Could not find some functions in '%s': '%s'."),
			filename, lt_dlerror ());
		lt_dlclose (lh);
		return (0);
	}

	type = lib_type ();
	for (j = 0; j < list->count; j++)
		if (list->info[j].type == type)
			break;
	if (j != list->count) {
		gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list",
			_("'%s' already loaded"), filename);
		lt_dlclose (lh);
		return (0);
	}

	result = lib_list (list);
	lt_dlclose (lh);
	if (result < 0) {
		gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list",
			_("Could not load port driver list: '%s'."),
			gp_port_result_as_string (result));
		return (0);
	}

	for (j = old_size; j < list->count; j++){
		gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list",
			_("Loaded '%s' ('%s') from '%s'."),
			list->info[j].name, list->info[j].path,
			filename);
		strcpy (list->info[j].library_filename, filename);
	}

	return (0);
}
Пример #4
0
static int
gp_port_serial_check_speed (GPPort *dev)
{
	speed_t speed;
#ifdef OS2
	ULONG rc;
	ULONG   ulParmLen = 2;     /* Maximum size of the parameter packet */
#else
#ifdef HAVE_TERMIOS_H
	struct termios tio;
#else
	struct sgttyb ttyb;
#endif
#endif

	/*
	 * We need an open device in order to set the speed. If there is no
	 * open device, postpone setting of speed.
	 */
	if (!dev->pl->fd)
		return (GP_OK);

	/* If baudrate is up to date, do nothing */
	if (dev->pl->baudrate == dev->settings.serial.speed)
		return (GP_OK);

	gp_log (GP_LOG_DEBUG, "gphoto2-port-serial",
		"Setting baudrate to %d...", dev->settings.serial.speed);
	speed = gp_port_serial_baudconv (dev->settings.serial.speed);

#ifdef OS2
	rc = DosDevIOCtl (dev->pl->fd,       /* Device handle               */
			  0x0001,            /* Serial-device control       */
			  0x0043,            /* Sets bit rate               */
			  (PULONG) &(dev->settings.serial.speed),
			  sizeof(baudrate),  /* Max. size of parameter list */
			  &ulParmLen,        /* Size of parameter packet    */
			  NULL,              /* No data packet              */
			  0,                 /* Maximum size of data packet */
			  NULL);             /* Size of data packet         */
	if(rc != 0)
		printf("DosDevIOCtl baudrate error:%d\n",rc);
#else /* !OS2 */
#ifdef HAVE_TERMIOS_H
        if (tcgetattr(dev->pl->fd, &tio) < 0) {
		gp_port_set_error (dev, _("Could not set the baudrate to %d"),
				   dev->settings.serial.speed);
                return GP_ERROR_IO_SERIAL_SPEED;
        }
        tio.c_cflag = (tio.c_cflag & ~CSIZE) | CS8;

        /* Set into raw, no echo mode */
        tio.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL |
                         IXANY | IXON | IXOFF | INPCK | ISTRIP);
#ifdef IUCLC
        tio.c_iflag &= ~IUCLC;
#endif
        tio.c_iflag |= (BRKINT | IGNPAR);
        tio.c_oflag &= ~OPOST;
        tio.c_lflag &= ~(ICANON | ISIG | ECHO | ECHONL | ECHOE |
                         ECHOK | IEXTEN);
        tio.c_cflag &= ~(CRTSCTS | PARENB | PARODD);
        tio.c_cflag |= CLOCAL | CREAD;

        tio.c_cc[VMIN] = 1;
        tio.c_cc[VTIME] = 0;

	if (dev->settings.serial.parity != GP_PORT_SERIAL_PARITY_OFF) {
	    tio.c_iflag &= ~IGNPAR;
	    tio.c_iflag |= INPCK | PARMRK ;
	    tio.c_cflag |= PARENB;
	    if (dev->settings.serial.parity == GP_PORT_SERIAL_PARITY_ODD)
		tio.c_cflag |= PARODD;
	}

	/* Set the new speed. */
	cfsetispeed (&tio, speed);
	cfsetospeed (&tio, speed);
        if (tcsetattr (dev->pl->fd, TCSANOW, &tio) < 0) {
		GP_DEBUG ("Error on 'tcsetattr'.");
                return GP_ERROR_IO_SERIAL_SPEED;
        }

	/* Clear O_NONBLOCK. */
        if (fcntl (dev->pl->fd, F_SETFL, 0) < 0) {
		GP_DEBUG ("Error on 'fcntl'.");
                return GP_ERROR_IO_SERIAL_SPEED;
        }

	/*
	 * Verify if the speed change has been successful.
	 * This is needed because some Solaris systems just ignore unsupported
	 * speeds (like 115200) instead of complaining.
	 *
	 * Only perform the check if we really changed to some speed.
	 */
	if (speed != B0) {
		if (tcgetattr (dev->pl->fd, &tio)) {
			GP_DEBUG ("Error on 'tcgetattr'.");
			return (GP_ERROR_IO_SERIAL_SPEED);
		}
		if ((cfgetispeed (&tio) != speed) ||
		    (cfgetospeed (&tio) != speed)) {
			GP_DEBUG ("Cannot set baudrate to %d...",
				  dev->settings.serial.speed);
			return (GP_ERROR_NOT_SUPPORTED);
		}
	}

#else /* !HAVE_TERMIOS_H */
        if (ioctl (dev->pl->fd, TIOCGETP, &ttyb) < 0) {
                perror("ioctl(TIOCGETP)");
                return GP_ERROR_IO_SERIAL_SPEED;
        }
        ttyb.sg_ispeed = dev->settings.serial.speed;
        ttyb.sg_ospeed = dev->settings.serial.speed;
        ttyb.sg_flags = 0;

        if (ioctl (dev->pl->fd, TIOCSETP, &ttyb) < 0) {
                perror("ioctl(TIOCSETP)");
                return GP_ERROR_IO_SERIAL_SPEED;
        }
#endif
#endif

	dev->pl->baudrate = dev->settings.serial.speed;
        return GP_OK;
}
Пример #5
0
static int
get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
	       CameraFileType type, CameraFile *file, void *data,
	       GPContext *context)
{
	Camera *camera = data;
	int result = GP_ERROR_IO;
	enum {
		START,
		DATA,
		ABORT
	} state;
	int r, pid = 0, update = 0;
	uint64_t byteCount = 0;
	struct utimbuf mod_utime_buf = { 0, 0 };
	char *path;
	struct tf_packet reply;

	if (type != GP_FILE_TYPE_NORMAL)
		return GP_ERROR_NOT_SUPPORTED;

	do_cmd_turbo (camera, "ON", context);

	path = get_path(camera, folder, filename);
	r = send_cmd_hdd_file_send(camera, GET, path, context);
	free (path);
	if(r < 0)
		goto out;

	state = START;
	while(0 < (r = get_tf_packet(camera, &reply, context)))
	{
		update = (update + 1) % 4;
		switch (get_u32(&reply.cmd)) {
		case DATA_HDD_FILE_START:
			if(state == START) {
				struct typefile *tf = (struct typefile *) reply.data;

				byteCount = get_u64(&tf->size);
				pid = gp_context_progress_start (context, byteCount, _("Downloading %s..."), filename);
				mod_utime_buf.actime = mod_utime_buf.modtime =
				tfdt_to_time(&tf->stamp);

				send_success(camera,context);
				state = DATA;
			} else {
				gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unexpected DATA_HDD_FILE_START packet in state %d\n", state);
				send_cancel(camera,context);
				state = ABORT;
			}
			break;

		case DATA_HDD_FILE_DATA:
			if(state == DATA) {
				uint64_t offset = get_u64(reply.data);
				uint16_t dataLen = get_u16(&reply.length) - (PACKET_HEAD_SIZE + 8);
				int w;

				if (!update) { /* avoid doing it too often */
					gp_context_progress_update (context, pid, offset + dataLen);
					if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
						send_cancel(camera,context);
						state = ABORT;
					}
				}

				if(r < get_u16(&reply.length)) {
					gp_log (GP_LOG_ERROR, "topfield", "ERROR: Short packet %d instead of %d\n", r, get_u16(&reply.length));
					/* TODO: Fetch the rest of the packet */
				}

				w = gp_file_append (file, (char*)&reply.data[8], dataLen);

				if(w < GP_OK) {
					/* Can't write data - abort transfer */
					gp_log (GP_LOG_ERROR, "topfield", "ERROR: Can not write data: %d\n", w);
					send_cancel(camera,context);
					state = ABORT;
				}
			} else {
				gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unexpected DATA_HDD_FILE_DATA packet in state %d\n", state);
				send_cancel(camera,context);
				state = ABORT;
			}
			break;

		case DATA_HDD_FILE_END:
			send_success(camera,context);
			result = GP_OK;
			goto out;
			break;

		case FAIL:
			gp_log (GP_LOG_ERROR, "topfield", "ERROR: Device reports %s\n", decode_error(&reply));
			send_cancel(camera,context);
			state = ABORT;
			break;

		case SUCCESS:
			goto out;
			break;

		default:
			gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unhandled packet (cmd 0x%x)\n", get_u32(&reply.cmd));
			break;
		}
	}
	if (pid) gp_context_progress_stop (context, pid);
out:
	do_cmd_turbo (camera, "OFF", context);
	return result;
}
Пример #6
0
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);
}
Пример #7
0
static int
gp_port_usb_find_device_lib(GPPort *port, int idvendor, int idproduct)
{
	char *s;
	int d, busnr = 0, devnr = 0;
	GPPortPrivateLibrary *pl;

	if (!port)
		return (GP_ERROR_BAD_PARAMETERS);

	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 ret;
		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 (GP_LOG_VERBOSE, "libusb1",
			"Looking for USB device "
			"(vendor 0x%x, product 0x%x)... found.", 
			idvendor, idproduct);

		/* Use the first config, interface and altsetting we find */
		gp_port_usb_find_first_altsetting(pl->devs[d], &config, &interface, &altsetting);

		ret = libusb_get_config_descriptor (pl->devs[d], config, &confdesc);
		if (ret)
			continue;

		/* Set the defaults */
		if (confdesc->interface[interface].altsetting[altsetting].bInterfaceClass
		    == LIBUSB_CLASS_MASS_STORAGE) {
			gp_log (GP_LOG_VERBOSE, "libusb1",
				_("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_port_usb_find_ep(pl->devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_IN, LIBUSB_TRANSFER_TYPE_BULK);
		port->settings.usb.outep = gp_port_usb_find_ep(pl->devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_OUT, LIBUSB_TRANSFER_TYPE_BULK);
		port->settings.usb.intep = gp_port_usb_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 (GP_LOG_VERBOSE, "libusb1",
			"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;
}
Пример #8
0
/* This function reads the Microsoft OS Descriptor and looks inside to
 * find if it is a MTP device. This is the similar to the way that
 * Windows Media Player 10 uses.
 * It is documented to some degree on various internet pages.
 */
static int
gp_port_usb_match_mtp_device(struct usb_device *dev,int *configno, int *interfaceno, int *altsettingno)
{
	char buf[1000], cmd;
	int ret,i,i1,i2, xifaces,xnocamifaces;
	usb_dev_handle *devh;

	/* All of them are "vendor specific" device class */
#if 0
	if ((dev->descriptor.bDeviceClass!=0xff) && (dev->descriptor.bDeviceClass!=0))
		return 0;
#endif
	if (dev->config) {
		xifaces = xnocamifaces = 0;
		for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
			unsigned int j;

			for (j = 0; j < dev->config[i].bNumInterfaces; j++) {
				int k;
				xifaces++;

				for (k = 0; k < dev->config[i].interface[j].num_altsetting; k++) {
					struct usb_interface_descriptor *intf = &dev->config[i].interface[j].altsetting[k]; 
					if (	(intf->bInterfaceClass == USB_CLASS_HID)	||
						(intf->bInterfaceClass == USB_CLASS_PRINTER)	||
						(intf->bInterfaceClass == USB_CLASS_AUDIO)	||
						(intf->bInterfaceClass == USB_CLASS_HUB)	||
						(intf->bInterfaceClass == USB_CLASS_COMM)	||
						(intf->bInterfaceClass == 0xe0)	/* wireless/bluetooth*/
					)
						xnocamifaces++;
				}
			}
		}
	}
	if (xifaces == xnocamifaces) /* only non-camera ifaces */
		return 0;

	/* Marcus: Avoid this probing altogether, its too unstable on some devices */
	return 0;

#if 0
	devh = usb_open (dev);
	if (!devh)
		return 0;

	/*
	 * Loop over the device configurations and interfaces. Nokia MTP-capable 
	 * handsets (possibly others) typically have the string "MTP" in their 
	 * MTP interface descriptions, that's how they can be detected, before
	 * we try the more esoteric "OS descriptors" (below).
	 */
	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
		unsigned int j;
		for (j = 0; j < dev->config[i].bNumInterfaces; j++) {
			int k;
			for (k = 0; k < dev->config[i].interface[j].num_altsetting; k++) {
				buf[0] = '\0';
				ret = usb_get_string_simple(devh, 
					dev->config[i].interface[j].altsetting[k].iInterface, 
					(char *) buf, 
					1024);
				if (ret < 3)
					continue;
				if (strcmp((char *) buf, "MTP") == 0) {
					gp_log (GP_LOG_DEBUG, "mtp matcher", "Configuration %d, interface %d, altsetting %d:\n", i, j, k);
					gp_log (GP_LOG_DEBUG, "mtp matcher", "   Interface description contains the string \"MTP\"\n");
					gp_log (GP_LOG_DEBUG, "mtp matcher", "   Device recognized as MTP, no further probing.\n");
					goto found;
				}
			}
		}
	}

	/* get string descriptor at 0xEE */
	ret = usb_get_descriptor (devh, 0x03, 0xee, buf, sizeof(buf));
	if (ret > 0) gp_log_data("get_MS_OSD",buf, ret);
	if (ret < 10) goto errout;
	if (!((buf[2] == 'M') && (buf[4]=='S') && (buf[6]=='F') && (buf[8]=='T')))
		goto errout;
	cmd = buf[16];
	ret = usb_control_msg (devh, USB_ENDPOINT_IN|USB_RECIP_DEVICE|USB_TYPE_VENDOR, cmd, 0, 4, buf, sizeof(buf), 1000);
	if (ret == -1) {
		gp_log (GP_LOG_ERROR, "mtp matcher", "control message says %d\n", ret);
		goto errout;
	}
	if (buf[0] != 0x28) {
		gp_log (GP_LOG_ERROR, "mtp matcher", "ret is %d, buf[0] is %x\n", ret, buf[0]);
		goto errout;
	}
	if (ret > 0) gp_log_data("get_MS_ExtDesc",buf, ret);
	if ((buf[0x12] != 'M') || (buf[0x13] != 'T') || (buf[0x14] != 'P')) {
		gp_log (GP_LOG_ERROR, "mtp matcher", "buf at 0x12 is %02x%02x%02x\n", buf[0x12], buf[0x13], buf[0x14]);
		goto errout;
	}
	ret = usb_control_msg (devh, USB_ENDPOINT_IN|USB_RECIP_DEVICE|USB_TYPE_VENDOR, cmd, 0, 5, buf, sizeof(buf), 1000);
	if (ret == -1) goto errout;
	if (buf[0] != 0x28) {
		gp_log (GP_LOG_ERROR, "mtp matcher", "ret is %d, buf[0] is %x\n", ret, buf[0]);
		goto errout;
	}
	if (ret > 0) gp_log_data("get_MS_ExtProp",buf, ret);
	if ((buf[0x12] != 'M') || (buf[0x13] != 'T') || (buf[0x14] != 'P')) {
		gp_log (GP_LOG_ERROR, "mtp matcher", "buf at 0x12 is %02x%02x%02x\n", buf[0x12], buf[0x13], buf[0x14]);
		goto errout;
	}

found:
	usb_close (devh);

	/* Now chose a nice interface for us to use ... Just take the first. */

	if (dev->descriptor.bNumConfigurations > 1)
		gp_log (GP_LOG_ERROR, "mtp matcher", "The device has %d configurations!\n", dev->descriptor.bNumConfigurations);
	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
		struct usb_config_descriptor *config =
			&dev->config[i];

		if (config->bNumInterfaces > 1)
			gp_log (GP_LOG_ERROR, "mtp matcher", "The configuration has %d interfaces!\n", config->bNumInterfaces);
		for (i1 = 0; i1 < config->bNumInterfaces; i1++) {
			struct usb_interface *interface =
				&config->interface[i1];

			if (interface->num_altsetting > 1)
				gp_log (GP_LOG_ERROR, "mtp matcher", "The interface has %d altsettings!\n", interface->num_altsetting);
			for (i2 = 0; i2 < interface->num_altsetting; i2++) {
				*configno = i;
				*interfaceno = i1;
				*altsettingno = i2;
				return 1;
			}
		}
	}
	return 1;
errout:
	usb_close (devh);
	return 0;
#endif
}
Пример #9
0
/**
 * \brief Send a SCSI command to a port (for usb scsi ports)
 *
 * \param port a #GPPort
 * \param to_dev data direction, set to 1 for a scsi cmd which sends
 *        data to the device, set to 0 for cmds which read data from the dev.
 * \param cmd buffer holding the command to send
 * \param cmd_size sizeof cmd buffer
 * \param sense buffer for returning scsi sense information
 * \param sense_size sizeof sense buffer
 * \param data buffer containing informatino to write to the device
 *        (to_dev is 1), or to store data read from the device (to_dev 0).
 *
 * Send a SCSI command to a usb scsi port attached device.
 *
 * \return a gphoto2 error code
 **/
int gp_port_send_scsi_cmd (GPPort *port, int to_dev,
				char *cmd, int cmd_size,
				char *sense, int sense_size,
				char *data, int data_size)
{
	int retval;

	gp_log (GP_LOG_DEBUG, "gphoto2-port", "Sending scsi cmd:");
	gp_log_data ("gphoto2-port", cmd, cmd_size);
	if (to_dev && data_size) {
		gp_log (GP_LOG_DEBUG, "gphoto2-port", "scsi cmd data:");
		gp_log_data ("gphoto2-port", data, data_size);
	}

	CHECK_NULL (port);
	CHECK_INIT (port);

	memset (sense, 0, sense_size);
	CHECK_SUPP (port, "send_scsi_cmd", port->pc->ops->send_scsi_cmd);
	retval = port->pc->ops->send_scsi_cmd (port, to_dev, cmd, cmd_size,
					sense, sense_size, data, data_size);

	gp_log (GP_LOG_DEBUG, "gphoto2-port", "scsi cmd result: %d", retval);

	if (sense[0] != 0) {
		gp_log (GP_LOG_DEBUG, "gphoto2-port", "sense data:");
		gp_log_data ("gphoto2-port", sense, sense_size);
		/* https://secure.wikimedia.org/wikipedia/en/wiki/Key_Code_Qualifier */
		gp_log(GP_LOG_DEBUG, "gphoto2-port","sense decided:");
		if ((sense[0]&0x7f)!=0x70) {
			gp_log(GP_LOG_DEBUG, "gphoto2-port","\tInvalid header.");
		}
		gp_log(GP_LOG_DEBUG, "gphoto2-port", "\tCurrent command read filemark: %s",(sense[2]&0x80)?"yes":"no");
		gp_log(GP_LOG_DEBUG, "gphoto2-port", "\tEarly warning passed: %s",(sense[2]&0x40)?"yes":"no");
		gp_log(GP_LOG_DEBUG, "gphoto2-port", "\tIncorrect blocklengt: %s",(sense[2]&0x20)?"yes":"no");
		gp_log(GP_LOG_DEBUG, "gphoto2-port", "\tSense Key: %d",sense[2]&0xf);
		if (sense[0]&0x80)
			gp_log(GP_LOG_DEBUG, "gphoto2-port", "\tResidual Length: %d",sense[3]*0x1000000+sense[4]*0x10000+sense[5]*0x100+sense[6]);
		gp_log(GP_LOG_DEBUG, "gphoto2-port", "\tAdditional Sense Length: %d",sense[7]);
		gp_log(GP_LOG_DEBUG, "gphoto2-port", "\tAdditional Sense Code: %d",sense[12]);
		gp_log(GP_LOG_DEBUG, "gphoto2-port", "\tAdditional Sense Code Qualifier: %d",sense[13]);
		if (sense[15]&0x80) {
			gp_log(GP_LOG_DEBUG, "gphoto2-port", "\tIllegal Param is in %s",(sense[15]&0x40)?"the CDB":"the Data Out Phase");
			if (sense[15]&0x8) {
				gp_log(GP_LOG_DEBUG, "gphoto2-port", "Pointer at %d, bit %d",sense[16]*256+sense[17],sense[15]&0x7);
			}
		}
	}

	if (!to_dev && data_size) {
		gp_log (GP_LOG_DEBUG, "gphoto2-port", "scsi cmd data:");
		gp_log_data ("gphoto2-port", data, data_size);
	}

	return retval;
}
Пример #10
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_port_usb_update (GPPort *port)
{
	int ret, ifacereleased = FALSE;

	gp_log (GP_LOG_DEBUG, "libusb", "gp_port_usb_update(old int=%d, conf=%d, alt=%d), (new int=%d, conf=%d, alt=%d)",
		port->settings.usb.interface,
		port->settings.usb.config,
		port->settings.usb.altsetting,
		port->settings_pending.usb.interface,
		port->settings_pending.usb.config,
		port->settings_pending.usb.altsetting
	);
	if (!port)
		return GP_ERROR_BAD_PARAMETERS;

#if 0
	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;
#endif

	/* 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)
		return GP_ERROR_BAD_PARAMETERS;

	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 (GP_LOG_DEBUG, "libusb", "changing interface %d -> %d",
			port->pl->interface,
			port->settings.usb.interface
		);
		if (usb_release_interface (port->pl->dh,
					   port->pl->interface) < 0) {
			gp_log (GP_LOG_DEBUG, "gphoto2-port-usb","releasing the iface for config failed.");
			/* Not a hard error for now. -Marcus */
		} else {
			gp_log (GP_LOG_DEBUG,"libusb","claiming interface %d", port->settings.usb.interface);
			ret = usb_claim_interface (port->pl->dh,
						   port->settings.usb.interface);
			if (ret < 0) {
				gp_log (GP_LOG_DEBUG, "gphoto2-port-usb","reclaiming the iface for config failed.");
				return GP_ERROR_IO_UPDATE;
			}
			port->pl->interface = port->settings.usb.interface;
		}
	}
	if (port->settings.usb.config != port->pl->config) {
		gp_log (GP_LOG_DEBUG, "libusb", "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 (usb_release_interface (port->pl->dh,
					   port->settings.usb.interface) < 0) {
			gp_log (GP_LOG_DEBUG, "gphoto2-port-usb","releasing the iface for config failed.");
			ifacereleased = FALSE;
		} else {
			ifacereleased = TRUE;
		}
		ret = usb_set_configuration(port->pl->dh,
				     port->settings.usb.config);
		if (ret < 0) {
#if 0 /* setting the configuration failure is not fatal */
			gp_port_set_error (port,
				_("Could not set config %d/%d (%m)"),
				port->settings.usb.interface,
				port->settings.usb.config);
			return GP_ERROR_IO_UPDATE;	
#endif
			gp_log (GP_LOG_ERROR, "gphoto2-port-usb","setting configuration from %d to %d failed with ret = %d, but continue...", port->pl->config, port->settings.usb.config, ret);
		}

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

		if (ifacereleased) {
			gp_log (GP_LOG_DEBUG,"libusb","claiming interface %d", port->settings.usb.interface);
			ret = usb_claim_interface (port->pl->dh,
						   port->settings.usb.interface);
			if (ret < 0) {
				gp_log (GP_LOG_DEBUG, "gphoto2-port-usb","reclaiming the iface for config failed.");
			}
		}
		/*
		 * Copy at once if something else fails so that this
		 * does not get re-applied
		 */
		port->pl->config = port->settings.usb.config;
	}

	/* This can be changed with interface claimed. (And I think it must be claimed.) */
	if (port->settings.usb.altsetting != port->pl->altsetting) {
		ret = usb_set_altinterface(port->pl->dh, port->settings.usb.altsetting);
		if (ret < 0) {
			gp_port_set_error (port, 
				_("Could not set altsetting from %d "
				"to %d (%m)"),
				port->pl->altsetting,
				port->settings.usb.altsetting);
			return GP_ERROR_IO_UPDATE;
		}

		gp_log (GP_LOG_DEBUG, "gphoto2-port-usb",
			"Changed usb.altsetting from %d to %d",
			port->pl->altsetting,
			port->settings.usb.altsetting);
		port->pl->altsetting = port->settings.usb.altsetting;
	}

	return GP_OK;
}
Пример #11
0
static int
gp_port_usb_find_device_lib(GPPort *port, int idvendor, int idproduct)
{
	struct usb_bus *bus;
	struct usb_device *dev;
	char *s;
	char busname[64], devname[64];

	if (!port)
		return (GP_ERROR_BAD_PARAMETERS);

	s = strchr (port->settings.usb.port,':');
	busname[0] = devname[0] = '\0';
	if (s && (s[1] != '\0')) { /* usb:%d,%d */
		strncpy(busname,s+1,sizeof(busname));
		busname[sizeof(busname)-1] = '\0';

		s = strchr(busname,',');
		if (s) {
			strncpy(devname, s+1,sizeof(devname));
			devname[sizeof(devname)-1] = '\0';
			*s = '\0';
		} else {
			busname[0] = '\0';
		}
	}
	/*
	 * NULL idvendor is not valid.
	 * NULL 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;
	}

	for (bus = usb_busses; bus; bus = bus->next) {
		if ((busname[0] != '\0') && strcmp(busname, bus->dirname))
			continue;

		for (dev = bus->devices; dev; dev = dev->next) {
			if (	(devname[0] != '\0') &&
				(dev->filename != strstr(dev->filename, devname))
			)
				continue;

			if ((dev->descriptor.idVendor == idvendor) &&
			    (dev->descriptor.idProduct == idproduct)) {
				int config = -1, interface = -1, altsetting = -1;

				port->pl->d = dev;

				gp_log (GP_LOG_VERBOSE, "gphoto2-port-usb",
					"Looking for USB device "
					"(vendor 0x%x, product 0x%x)... found.", 
					idvendor, idproduct);

				/* Use the first config, interface and altsetting we find */
				gp_port_usb_find_first_altsetting(dev, &config, &interface, &altsetting);

				/* Set the defaults */
				if (dev->config) {
					int i;

					if (dev->config[config].interface[interface].altsetting[altsetting].bInterfaceClass
					    == USB_CLASS_MASS_STORAGE) {
						gp_log (GP_LOG_VERBOSE, "gphoto2-port-usb",
							_("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 = dev->config[config].bConfigurationValue;
					port->settings.usb.interface = dev->config[config].interface[interface].altsetting[altsetting].bInterfaceNumber;
					port->settings.usb.altsetting = dev->config[config].interface[interface].altsetting[altsetting].bAlternateSetting;

					port->settings.usb.inep = gp_port_usb_find_ep(dev, config, interface, altsetting, USB_ENDPOINT_IN, USB_ENDPOINT_TYPE_BULK);
					port->settings.usb.outep = gp_port_usb_find_ep(dev, config, interface, altsetting, USB_ENDPOINT_OUT, USB_ENDPOINT_TYPE_BULK);
					port->settings.usb.intep = gp_port_usb_find_ep(dev, config, interface, altsetting, USB_ENDPOINT_IN, USB_ENDPOINT_TYPE_INTERRUPT);

					port->settings.usb.maxpacketsize = 0;
					gp_log (GP_LOG_DEBUG, "gphoto2-port-usb", "inep to look for is %02x", port->settings.usb.inep);
					for (i=0;i<dev->config[config].interface[interface].altsetting[altsetting].bNumEndpoints;i++) {
						if (port->settings.usb.inep == dev->config[config].interface[interface].altsetting[altsetting].endpoint[i].bEndpointAddress) {
							port->settings.usb.maxpacketsize = dev->config[config].interface[interface].altsetting[altsetting].endpoint[i].wMaxPacketSize;
							break;
						}
					}
					gp_log (GP_LOG_VERBOSE, "gphoto2-port-usb",
						"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,
						dev->config[config].interface[interface].altsetting[altsetting].bInterfaceClass,
						dev->config[config].interface[interface].altsetting[altsetting].bInterfaceSubClass
						);
				}

				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;
}
Пример #12
0
GPPortType
gp_port_library_type (void)
{
	gp_log(GP_LOG_DEBUG,__FUNCTION__,"()");
        return GP_PORT_USB;
}
Пример #13
0
static int
gp_port_vusb_update (GPPort *port)
{
	gp_log(GP_LOG_DEBUG,__FUNCTION__,"()");
	return GP_OK;
}
Пример #14
0
static int
gp_port_vusb_read(GPPort *port, char *bytes, int size)
{
	gp_log(GP_LOG_DEBUG,__FUNCTION__,"()");
	return port->pl->vcamera->read(port->pl->vcamera, 0x81, (unsigned char*)bytes, size);
}
Пример #15
0
/** 
 * Get list of supported cameras, walk through it and create some output.
 */
int
main (int argc, char *argv[])
{
	CameraAbilitiesList *al;
	int i;
	int count;
	const char *fmt_str = NULL;

	parse_command_line (argc, argv);

	if (do_debug) {
		gettimeofday (&glob_tv_zero, NULL);
		CHECK (gp_log_add_func (GP_LOG_ALL, debug_func, NULL));
		
		gp_log (GP_LOG_DEBUG, "main", "test-camera-list start");
	}


	CHECK (gp_abilities_list_new (&al));
	CHECK (gp_abilities_list_load (al, NULL));

	count = gp_abilities_list_count (al);
	if (count < 0) {
		printf("gp_abilities_list_count error: %d\n", count);
		return(1);
	} else if (count == 0) {
		/* Copied from gphoto2-abilities-list.c gp_abilities_list_load() */
		const char *camlib_env = getenv(CAMLIBDIR_ENV);
		const char *camlibs = (camlib_env != NULL)?camlib_env:CAMLIBS;

		printf("no camera drivers (camlibs) found in camlib dir:\n"
		       "    CAMLIBS='%s', default='%s', used=%s\n",
		       camlib_env?camlib_env:"(null)", CAMLIBS,
		       (camlib_env!=NULL)?"CAMLIBS":"default");
		return(1);
	}


	/* Set output format for file body, 
	 * and print opening part of output file. */
	switch (format) {
	case FMT_CSV:
		fmt_str = "%d,%s,%s,%s\n";
		break;
	case FMT_FLAT_TEXT:
		fmt_str = "%3d|%-20s|%-20s|%s\n";
		break;
	case FMT_HEADED_TEXT:
		fmt_str = "%3d|%-20s|%-20s|%s\n";
		break;
	case FMT_XML:
		fmt_str = "  <camera name=\"%4$s\" entry_number=\"%1$d\">\n"
			"    <camlib-name value=\"%2$s\"/>\n"
			"    <driver-name value=\"%3$s\"/>\n"
			"  </camera>\n";
		printf("<?xml version=\"%s\" encoding=\"%s\"?>\n"
		       "<camera-list camera-count=\"%d\">\n", 
		       "1.0", "us-ascii", count);
		break;
	case FMT_FLAT_CAMLIBS:
		fmt_str = "%2$-28s  %3$s\n";
		break;
	case FMT_COUNT:
		printf("%d\n", count);
		return(0);
		break;
	}

	/* For each camera in the list, add a text snippet to the 
	 * output file. */
	for (i = 0; i < count; i++) {
		CameraAbilities abilities;
		const char *camlib_basename;
		CHECK (gp_abilities_list_get_abilities (al, i, &abilities));
		camlib_basename = path_basename(abilities.library);

		switch (format) {
		case FMT_HEADED_TEXT:
			if ( ((i%25)== 0) && 
			     ( (i==0) || ((count-i) > 5) ) ) {
				print_hline();
				print_headline();
				print_hline();
			}
			break;
		case FMT_FLAT_CAMLIBS:
			break;
		case FMT_XML:
			break;
		case FMT_CSV:
			break;
		case FMT_FLAT_TEXT:
			break;
		case FMT_COUNT:
			break;
		}

		printf(fmt_str,
		       i+1, 
		       camlib_basename,
		       abilities.id,
		       abilities.model);
	}

	/* Print closing part of output file. */
	switch (format) {
	case FMT_HEADED_TEXT:
		print_hline();
		print_headline();
		print_hline();
		break;
	case FMT_FLAT_CAMLIBS:
		break;
	case FMT_XML:
		printf("</camera-list>\n");
		break;
	case FMT_CSV:
		break;
	case FMT_FLAT_TEXT:
		break;
	case FMT_COUNT:
		break;
	}
	
	CHECK (gp_abilities_list_free (al));
	return (0);
}
Пример #16
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)
{
	GPPortLibraryOperations ops_func;

	CHECK_NULL (port);

	if (port->pc->info.name) free (port->pc->info.name);
	port->pc->info.name = strdup (info->name);
	if (port->pc->info.path) free (port->pc->info.path);
	port->pc->info.path = strdup (info->path);
	port->pc->info.type = info->type;
	if (port->pc->info.library_filename) free (port->pc->info.library_filename);
	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) {
		lt_dlclose (port->pc->lh);
		lt_dlexit ();
	}

	lt_dlinit ();
	port->pc->lh = lt_dlopenext (info->library_filename);
	if (!port->pc->lh) {
		gp_log (GP_LOG_ERROR, "gphoto2-port", _("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 (GP_LOG_ERROR, "gphoto2-port", _("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:
		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;
	}
	gp_port_set_settings (port, port->settings);

	return (GP_OK);
}
Пример #17
0
/*
 * Function that downloads image
 *
 * Camera camera  : camera structure
 * int    index   : image index ( in gphoto point of view) -1 for real index
 * char*  toc     : pointer to toc
 * char** img_buf : returned image data
 * int* img_size      : returned image data size  
 *
 */
static int enigma13_download_img(Camera *camera, char *toc, int index, char **img_data, int *img_size)
{
	uint8_t *p;
	uint32_t file_size = 0, aligned_size = 0;
	char* buf=NULL; 
	int align=0;
	char  retbuf[2];

	gp_log(GP_LOG_DEBUG, "enigma13","DOWNLOADING IMAGE NO %d",index);

	/* Offset for image informations .
	Each image has 16 bytes for name and 16 for size, and others*/
	p = toc + (index*2)*32;

	/* real size from toc*/
	aligned_size = file_size =
		(p[0x1c] & 0xff)
		+ (p[0x1d] & 0xff) * 0x100
		+ (p[0x1e] & 0xff) * 0x10000;

	CHECK (gp_port_usb_msg_read (camera->port, 0x23,
		0x0000, 0x64,
		retbuf, 0x01));
	if (retbuf[0]==0x20){
		align=ENIGMA13_BLK_CARD_ALIGN;
		gp_log(GP_LOG_DEBUG, "enigma13"," Image from card, alignement is set to %d bytes ",align);
	} else if (retbuf[0]==0x10){
		align=ENIGMA13_BLK_FLASH_ALIGN;
		gp_log(GP_LOG_DEBUG, "enigma13"," Image from flash, alignement is set to %d bytes",align);
	} else {
		return GP_ERROR;
	}

	if (file_size % align != 0)
		aligned_size = ((file_size / align) + 1) * align;

	buf = (char*) malloc (aligned_size);
	if (!buf)
		return GP_ERROR_NO_MEMORY;

	CHECK_AND_FREE (gp_port_usb_msg_write (camera->port,
	0x54, index+1, 2, NULL, 0x00), buf);
	GP_SYSTEM_SLEEP(ENIGMA13_WAIT_IMAGE_READY_MS);

	CHECK_AND_FREE (gp_port_usb_msg_read (camera->port, 0x21,
		0x0000, 0x0000,
		buf, 0x01), buf);
	if (buf[0]!=0x41) {
		free (buf);
		return GP_ERROR;
	}

	CHECK_AND_FREE (gp_port_usb_msg_read (camera->port, 0x21,
		0x0000, 0x0002,
		buf, 0x01), buf);
	if (buf[0]!=0x01) {
		free (buf);
		return GP_ERROR;
	}

	CHECK_AND_FREE (gp_port_usb_msg_read (camera->port, 0x21,
		0x0000, 0x0002,
		buf, 0x01), buf);
	if (buf[0]!=0x01) {
		free (buf);
		return GP_ERROR;
	}
	gp_log(GP_LOG_DEBUG, "enigma13","READY FOR TRANSFER");
	CHECK_AND_FREE (gp_port_read (camera->port, buf, aligned_size), buf);
	*img_data=buf;
	*img_size=file_size;
	return GP_OK;
}
Пример #18
0
/**
 * \brief Log data
 * \brief domain the domain
 * \brief data the data to be logged
 * \brief size the size of the data
 *
 * Takes the data and creates a formatted hexdump string. If you would like
 * to log text messages, use #gp_log instead.
 **/
void
gp_log_data (const char *domain, const char *data, unsigned int size)
{
	static const char hexchars[16] = "0123456789abcdef";
	char *curline, *result;
	int x = HEXDUMP_INIT_X;
	int y = HEXDUMP_INIT_Y;
	unsigned int index;
	unsigned char value;

	if (!data) {
		gp_log (GP_LOG_DATA, domain, _("No hexdump (NULL buffer)"));
		return;
	}

	if (!size) {
		gp_log (GP_LOG_DATA, domain, _("Empty hexdump of empty buffer"));
		return;
	}

	if (size > 1024*1024) {
		/* Does not make sense for 200 MB movies */
		gp_log (GP_LOG_DATA, domain, _("Truncating dump from %d bytes to 1MB"), size);
		size = 1024*1024;
	}

	curline = result = malloc ((HEXDUMP_LINE_WIDTH+1)*(((size-1)/16)+1)+1);
	if (!result) {
		gp_log (GP_LOG_ERROR, "gphoto2-log", _("Malloc for %i bytes "
			"failed"), (HEXDUMP_LINE_WIDTH+1)*(((size-1)/16)+1)+1);
		return;
	}

	for (index = 0; index < size; ++index) {
                value = (unsigned char)data[index];
                curline[x] = hexchars[value >> 4];
                curline[x+1] = hexchars[value & 0xf];
                curline[x+2] = ' ';
                curline[y++] = ((value>=32)&&(value<127))?value:'.';
                x += 3;
                if ((index & 0xf) == 0xf) { /* end of line */
                        x = HEXDUMP_INIT_X;
                        y = HEXDUMP_INIT_Y;
                        HEXDUMP_COMPLETE_LINE;
                }
        }
        if ((index & 0xf) != 0) { /* not at end of line yet? */
                /* if so, complete this line */
                while (y < HEXDUMP_INIT_Y + 16) {
                        curline[x+0] = ' ';
                        curline[x+1] = ' ';
                        curline[x+2] = ' ';
                        curline[y++] = ' ';
                        x += 3;
                }
                HEXDUMP_COMPLETE_LINE;
        }
        curline[0] = '\0';

	gp_log (GP_LOG_DATA, domain, _("Hexdump of %i = 0x%x bytes follows:\n%s"),
		size, size, result);
	free (result);
}
Пример #19
0
static int
gp_port_usb_open (GPPort *port)
{
	int ret;

	gp_log (GP_LOG_DEBUG,"libusb1","gp_port_usb_open()");
	if (!port || !port->pl->d)
		return GP_ERROR_BAD_PARAMETERS;

	ret = libusb_open (port->pl->d, &port->pl->dh);
	if (ret) {
		gp_log (GP_LOG_ERROR, "libusb1", "libusb_open returned %d", ret);
		return 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 (GP_LOG_DEBUG,"libusb1",_("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:
		if (errno != ENODATA) /* ENODATA - just no driver there */
			gp_port_set_error (port, _("Could not query kernel driver of device."));
	}

	gp_log (GP_LOG_DEBUG,"libusb1","claiming interface %d", port->settings.usb.interface);
	ret = libusb_claim_interface (port->pl->dh,
				   port->settings.usb.interface);
	if (ret < 0) {
		int saved_errno = errno;
		gp_port_set_error (port, _("Could not claim interface %d (%s). "
					   "Make sure no other program "
					   "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),
				   "sdc2xx, stv680, spca50x");
		return GP_ERROR_IO_USB_CLAIM;
	}
	return GP_OK;
}
Пример #20
0
static int
gp_port_usb_find_path_lib(GPPort *port)
{
	char *s;
	int d, busnr = 0, devnr = 0;
	GPPortPrivateLibrary *pl;

	if (!port)
		return (GP_ERROR_BAD_PARAMETERS);

	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)
			return GP_ERROR_BAD_PARAMETERS;
	} else {
		return GP_ERROR_BAD_PARAMETERS;
	}

	pl->nrofdevs = load_devicelist (port->pl);

	for (d = 0; d < pl->nrofdevs; d++) {
		struct libusb_config_descriptor *confdesc;
		int ret;
		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 (GP_LOG_VERBOSE, "libusb1", "Found path %s", port->settings.usb.port); 

		/* Use the first config, interface and altsetting we find */
		gp_port_usb_find_first_altsetting(pl->devs[d], &config, &interface, &altsetting);

		ret = libusb_get_config_descriptor (pl->devs[d], config, &confdesc);
		if (ret)
			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_port_usb_find_ep(pl->devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_IN, LIBUSB_TRANSFER_TYPE_BULK);
		port->settings.usb.outep = gp_port_usb_find_ep(pl->devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_OUT, LIBUSB_TRANSFER_TYPE_BULK);
		port->settings.usb.intep = gp_port_usb_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 (GP_LOG_VERBOSE, "libusb1",
			"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;
}