Пример #1
0
/**
 * Retrieves information about a file.
 *
 * @param camera a #Camera
 * @param folder a folder
 * @param file the name of the file
 * @param info
 * @param context a #GPContext
 * @return a gphoto2 error code
 *
 **/
int
gp_camera_file_get_info (Camera *camera, const char *folder, 
			 const char *file, CameraFileInfo *info,
			 GPContext *context)
{
	int result = GP_OK;
	const char *mime_type;
	const char *data;
	/* long int size; */
	CameraFile *cfile;

	GP_LOG_D ("Getting file info for '%s' in '%s'...", file, folder);

	C_PARAMS (camera && folder && file && info);
	CHECK_INIT (camera, context);

	memset (info, 0, sizeof (CameraFileInfo));

	/* Check first if the camera driver supports the filesystem */
	CHECK_OPEN (camera, context);
	result = gp_filesystem_get_info (camera->fs, folder, file, info,
					 context);
	CHECK_CLOSE (camera, context);
	if (result != GP_ERROR_NOT_SUPPORTED) {
		CAMERA_UNUSED (camera, context);
		return (result);
	}

	/*
	 * The CameraFilesystem doesn't support file info. We simply get
	 * the preview and the file and look for ourselves...
	 */

	/* It takes too long to get the file */
	info->file.fields = GP_FILE_INFO_NONE;

	/* Get the preview */
	info->preview.fields = GP_FILE_INFO_NONE;
	CRS (camera, gp_file_new (&cfile), context);
	if (gp_camera_file_get (camera, folder, file, GP_FILE_TYPE_PREVIEW,
						cfile, context) == GP_OK) {
		unsigned long size;
		info->preview.fields |= GP_FILE_INFO_SIZE | GP_FILE_INFO_TYPE;
		gp_file_get_data_and_size (cfile, &data, &size);
		info->preview.size = size;
		gp_file_get_mime_type (cfile, &mime_type);
		strncpy (info->preview.type, mime_type,
			 sizeof (info->preview.type));
	}
	gp_file_unref (cfile);

	CAMERA_UNUSED (camera, context);
	return (GP_OK);
}
Пример #2
0
uint16_t
ptp_usb_control_device_reset_request (PTPParams *params) {
	Camera	*camera = ((PTPData *)params->data)->camera;
	int	ret;

	GP_LOG_D ("Sending usb device reset request.");
	ret = gp_port_usb_msg_class_write (camera->port, 0x66, 0x0000, 0x0000, NULL, 0);
	if (ret < GP_OK)
		return PTP_ERROR_IO;
	return PTP_RC_OK;
}
Пример #3
0
static int
_close_async_interrupts(GPPort *port)
{
	int i, haveone;
	struct timeval tv;

	C_PARAMS (port);

	if (port->pl->dh == NULL)
		return GP_OK;

	/* Catch up on pending ones */
	tv.tv_sec = 0;
	tv.tv_usec = 1000;
	LOG_ON_LIBUSB_E (libusb_handle_events_timeout(port->pl->ctx, &tv));
	/* Now cancel and free the async transfers */
	for (i = 0; i < sizeof(port->pl->transfers)/sizeof(port->pl->transfers[0]); i++) {
		if (port->pl->transfers[i]) {
			GP_LOG_D("canceling transfer %d:%p (status %d)",i, port->pl->transfers[i], port->pl->transfers[i]->status);
			/* this happens if the transfer is completed for instance, but not reaped. we cannot cancel it. */
			if (LOG_ON_LIBUSB_E(libusb_cancel_transfer(port->pl->transfers[i])) < 0) {
				libusb_free_transfer (port->pl->transfers[i]);
				port->pl->transfers[i] = NULL;
			}
		}
	}
	tv.tv_sec = 0;
	tv.tv_usec = 0;
	LOG_ON_LIBUSB_E (libusb_handle_events_timeout(port->pl->ctx, &tv));
	/* Do just one round ... this should be sufficient and avoids endless loops. */
	haveone = 0;
	for (i = 0; i < sizeof(port->pl->transfers)/sizeof(port->pl->transfers[0]); i++) {
		if (port->pl->transfers[i]) {
			GP_LOG_D("checking: transfer %d:%p status %d",i, port->pl->transfers[i], port->pl->transfers[i]->status);
			haveone = 1;
		}
	}
	if (haveone)
		LOG_ON_LIBUSB_E (libusb_handle_events(port->pl->ctx));
	return GP_OK;
}
Пример #4
0
uint16_t
ptp_usb_control_get_extended_event_data (PTPParams *params, char *buffer, int *size) {
	Camera	*camera = ((PTPData *)params->data)->camera;
	int	ret;

	GP_LOG_D ("Getting extended event data.");
	ret = gp_port_usb_msg_class_read (camera->port, 0x65, 0x0000, 0x0000, buffer, *size);
	if (ret < GP_OK)
		return PTP_ERROR_IO;
	*size = ret;
	return PTP_RC_OK;
}
Пример #5
0
/**
 * \brief Flush data on serial port
 *
 * \param port a GPPort
 * \param direction the direction of the flush
 *
 * Flushes the serial output or input (depending on direction)
 * of the serial port.
 *
 * \return a gphoto2 error code
 */
int
gp_port_flush (GPPort *port, int direction)
{
	GP_LOG_D ("Flushing port...");

	C_PARAMS (port);

	CHECK_SUPP (port, "flush", port->pc->ops->flush);
	CHECK_RESULT (port->pc->ops->flush (port, direction));

        return (GP_OK);
}
Пример #6
0
/**
 * \brief Close a port.
 * \param port a #GPPort
 *
 * Closes a port temporarily. It can afterwards be reopened using
 * #gp_port_open.
 *
 * \return a gphoto2 error code
 **/
int
gp_port_close (GPPort *port)
{
	GP_LOG_D ("Closing port...");

	C_PARAMS (port);
	CHECK_INIT (port);

	CHECK_SUPP (port, "close", port->pc->ops->close);
        CHECK_RESULT (port->pc->ops->close(port));

	return (GP_OK);
}
Пример #7
0
/**
 * \brief Send a break over a serial port
 *
 * \param port a GPPort
 * \param duration duration of break in milliseconds
 *
 * Sends a break with the specified duration in milliseconds.
 *
 * \return a gphoto2 error code
 */
int
gp_port_send_break (GPPort *port, int duration)
{
	GP_LOG_D ("Sending break (%i milliseconds)...", duration);

	C_PARAMS (port);
	CHECK_INIT (port);

        CHECK_SUPP (port, "send_break", port->pc->ops->send_break);
        CHECK_RESULT (port->pc->ops->send_break (port, duration));

	return (GP_OK);
}
Пример #8
0
/**
 * \brief Clear USB endpoint HALT condition
 *
 * \param port a GPPort
 * \param ep endpoint to clear HALT
 *
 * Clears the HALT (stall?) endpoint condition of the specified endpoint.
 *
 * \return a gphoto2 error code
 */
int
gp_port_usb_clear_halt (GPPort *port, int ep)
{
	GP_LOG_D ("Clear USB halt...");

	C_PARAMS (port);
	CHECK_INIT (port);

	CHECK_SUPP (port, "clear_halt", port->pc->ops->clear_halt);
        CHECK_RESULT (port->pc->ops->clear_halt (port, ep));

        return (GP_OK);
}
Пример #9
0
uint16_t
ptp_usb_sendreq (PTPParams* params, PTPContainer* req)
{
	int res, towrite, do_retry = TRUE;
	PTPUSBBulkContainer usbreq;
	Camera *camera = ((PTPData *)params->data)->camera;

	GP_LOG_D ("Sending PTP_OC 0x%0x (%s) request...", req->Code, ptp_get_opcode_name(params, req->Code));

	/* build appropriate USB container */
	usbreq.length=htod32(PTP_USB_BULK_REQ_LEN-
		(sizeof(uint32_t)*(5-req->Nparam)));
	usbreq.type=htod16(PTP_USB_CONTAINER_COMMAND);
	usbreq.code=htod16(req->Code);
	usbreq.trans_id=htod32(req->Transaction_ID);
	usbreq.payload.params.param1=htod32(req->Param1);
	usbreq.payload.params.param2=htod32(req->Param2);
	usbreq.payload.params.param3=htod32(req->Param3);
	usbreq.payload.params.param4=htod32(req->Param4);
	usbreq.payload.params.param5=htod32(req->Param5);
	/* send it to responder */
	towrite = PTP_USB_BULK_REQ_LEN-(sizeof(uint32_t)*(5-req->Nparam));
retry:
	res = gp_port_write (camera->port, (char*)&usbreq, towrite);
	if (res != towrite) {
		if (res < 0) {
			GP_LOG_E ("PTP_OC 0x%04x sending req failed: %s (%d)", req->Code, gp_port_result_as_string(res), res);
			if (res == GP_ERROR_IO_WRITE && do_retry) {
				GP_LOG_D ("Clearing halt on OUT EP and retrying once.");
				gp_port_usb_clear_halt (camera->port, GP_PORT_USB_ENDPOINT_OUT);
				do_retry = FALSE;
				goto retry;
			}
		} else
			GP_LOG_E ("PTP_OC 0x%04x sending req failed: wrote only %d of %d bytes", req->Code, res, towrite);
		return PTP_ERROR_IO;
	}
	return PTP_RC_OK;
}
Пример #10
0
/**
 * \brief Reset a port.
 * \param port a #GPPort
 *
 * Resets a port. Device will likely reconnect and appear under a new id.
 *
 * \return a gphoto2 error code
 **/
int
gp_port_reset (GPPort *port)
{
	GP_LOG_D ("Resetting port...");

	C_PARAMS (port);
	CHECK_INIT (port);

	CHECK_SUPP (port, "reset", port->pc->ops->reset);
        CHECK_RESULT (port->pc->ops->reset(port));

	return (GP_OK);
}
Пример #11
0
/**
 * \brief Open a port.
 * \param port a #GPPort
 *
 * Opens a port which should have been created with #gp_port_new and 
 * configured with #gp_port_set_info and #gp_port_set_settings
 *
 * \return a gphoto2 error code
 **/
int
gp_port_open (GPPort *port)
{
	C_PARAMS (port);
	CHECK_INIT (port);

	GP_LOG_D ("Opening %s port...",
		  port->type == GP_PORT_SERIAL ? "SERIAL" : (port->type == GP_PORT_USB ? "USB" : ""));

	CHECK_SUPP (port, "open", port->pc->ops->open);
	CHECK_RESULT (port->pc->ops->open (port));

	return GP_OK;
}
Пример #12
0
static uint16_t
ptp_usb_getpacket(PTPParams *params, PTPUSBBulkContainer *packet, uint32_t *rlen)
{
	int		tries = 0, result;
	Camera		*camera = ((PTPData *)params->data)->camera;

	/* read the header and potentially the first data */
	if (params->response_packet_size > 0) {
		GP_LOG_D ("Returning previously buffered response packet.");
		/* If there is a buffered packet, just use it. */
		memcpy(packet, params->response_packet, params->response_packet_size);
		*rlen = params->response_packet_size;
		free(params->response_packet);
		params->response_packet = NULL;
		params->response_packet_size = 0;
		/* Here this signifies a "virtual read" */
		return PTP_RC_OK;
	}
retry:
	/* A packet should come in a single read always. */
	result = gp_port_read (camera->port, (char*)packet, sizeof(*packet));
	/* This might be a left over zero-write of the device at the end of the previous transmission */
	if (result == 0)
		result = gp_port_read (camera->port, (char*)packet, sizeof(*packet));
	if (result > 0) {
		*rlen = result;
		return PTP_RC_OK;
	}
	if (result == GP_ERROR_IO_READ) {
		GP_LOG_D ("Clearing halt on IN EP and retrying once.");
		gp_port_usb_clear_halt (camera->port, GP_PORT_USB_ENDPOINT_IN);
		/* retrying only makes sense if we did not read anything yet */
		if (tries++ < 1)
			goto retry;
	}
	return PTP_ERROR_IO;
}
Пример #13
0
/**
 * Deletes the file from \c folder.
 *
 * \param camera a #Camera
 * \param folder a folder
 * \param file the name of a file
 * \param context a #GPContext
 * \return a gphoto2 error code
 *
 **/
int
gp_camera_file_delete (Camera *camera, const char *folder, const char *file,
		       GPContext *context)
{
	GP_LOG_D ("Deleting file '%s' in folder '%s'...", file, folder);

	C_PARAMS (camera && folder && file);
	CHECK_INIT (camera, context);

	CHECK_RESULT_OPEN_CLOSE (camera, gp_filesystem_delete_file (
				camera->fs, folder, file, context), context);

	CAMERA_UNUSED (camera, context);
	return (GP_OK);
}
Пример #14
0
/**
 * Deletes all files in a given \c folder.
 *
 * @param camera a #Camera
 * @param folder a folder
 * @param context a #GPContext
 * @return a gphoto2 error code
 *
 **/
int
gp_camera_folder_delete_all (Camera *camera, const char *folder,
			     GPContext *context)
{
	GP_LOG_D ("Deleting all files in '%s'...", folder);

	C_PARAMS (camera && folder);
	CHECK_INIT (camera, context);

	CHECK_RESULT_OPEN_CLOSE (camera, gp_filesystem_delete_all (camera->fs,
						folder, context), context);

	CAMERA_UNUSED (camera, context);
	return (GP_OK);
}
Пример #15
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);
}
Пример #16
0
/**
 * Lists the folders in supplied \c folder.
 *
 * @param camera a #Camera
 * @param folder a folder
 * @param list a #CameraList
 * @param context a #GPContext
 * @return a gphoto2 error code
 *
 **/
int
gp_camera_folder_list_folders (Camera *camera, const char* folder, 
			       CameraList *list, GPContext *context)
{
	GP_LOG_D ("Listing folders in '%s'...", folder);

	C_PARAMS (camera && folder && list);
	CHECK_INIT (camera, context);
	CR (camera, gp_list_reset (list), context);

	CHECK_RESULT_OPEN_CLOSE (camera, gp_filesystem_list_folders (
				camera->fs, folder, list, context), context);

	CR (camera, gp_list_sort (list), context);
	CAMERA_UNUSED (camera, context);
        return (GP_OK);
}
Пример #17
0
/**
 * Uploads a file into given \c folder.
 *
 * @param camera a #Camera
 * @param folder a folder
 * @param file a #CameraFile
 * @param context a #GPContext
 * @return a gphoto2 error code
 *
 **/
int
gp_camera_folder_put_file (Camera *camera,
			   const char *folder, const char *filename,
			   CameraFileType type,
			   CameraFile *file, GPContext *context)
{
	GP_LOG_D ("Uploading file into '%s'...",
		folder);

	C_PARAMS (camera && folder && file);
	CHECK_INIT (camera, context);

	CHECK_RESULT_OPEN_CLOSE (camera, gp_filesystem_put_file (camera->fs,
					folder, filename, type, file, context), context);

	CAMERA_UNUSED (camera, context);
	return (GP_OK);
}
Пример #18
0
/**
 * \brief Sets the camera abilities. 
 *
 * @param camera a #Camera
 * @param abilities the #CameraAbilities to be set
 * @return a gphoto2 error code
 *
 * You need to call this function before calling #gp_camera_init the
 * first time unless you want gphoto2 to autodetect cameras and choose
 * the first detected one. By setting the \c abilities, you 
 * tell gphoto2 what model the \c camera is and what camera driver should 
 * be used for accessing the \c camera. You can get \c abilities by calling
 * #gp_abilities_list_get_abilities.
 *
 */
int
gp_camera_set_abilities (Camera *camera, CameraAbilities abilities)
{
	GP_LOG_D ("Setting abilities ('%s')...", abilities.model);

	C_PARAMS (camera);

	/*
	 * If the camera is currently initialized, terminate that connection.
	 * We don't care if we are successful or not.
	 */
	if (camera->pc->lh)
		gp_camera_exit (camera, NULL);

	memcpy (&camera->pc->a, &abilities, sizeof (CameraAbilities));

	return (GP_OK);
}
Пример #19
0
/**
 * Close connection to camera.
 *
 * @param camera a #Camera object
 * @param context a #GPContext object
 * @return a gphoto2 error code.
 *
 * Closes a connection to the camera and therefore gives other application
 * the possibility to access the camera, too.
 *
 * It is recommended that you 
 * call this function when you currently don't need the camera. The camera
 * will get reinitialized by gp_camera_init() automatically if you try to 
 * access the camera again.
 *
 */
int
gp_camera_exit (Camera *camera, GPContext *context)
{
	C_PARAMS (camera);

	GP_LOG_D ("Exiting camera ('%s')...", camera->pc->a.model);

	/*
	 * We have to postpone this operation if the camera is currently 
	 * in use. gp_camera_exit will be called again if the
	 * camera->pc->used will drop to zero.
	 */
	if (camera->pc->used) {
		camera->pc->exit_requested = 1;
		return (GP_OK);
	}

	/* Remove every timeout that is still pending */
	while (camera->pc->timeout_ids_len)
		gp_camera_stop_timeout (camera, camera->pc->timeout_ids[0]);
	free (camera->pc->timeout_ids);
	camera->pc->timeout_ids = NULL;

	if (camera->functions->exit) {
#ifdef HAVE_MULTI
		gp_port_open (camera->port);
#endif
		camera->functions->exit (camera, context);
	}
	gp_port_close (camera->port);
	memset (camera->functions, 0, sizeof (CameraFunctions));

	if (camera->pc->lh) {
#if !defined(VALGRIND)
		lt_dlclose (camera->pc->lh);
		lt_dlexit ();
#endif
		camera->pc->lh = NULL;
	}

	gp_filesystem_reset (camera->fs);

	return (GP_OK);
}
Пример #20
0
static int gp_port_usbscsi_send_scsi_cmd (GPPort *port, int to_dev, char *cmd,
        int cmd_size, char *sense, int sense_size, char *data, int data_size)
{
#ifdef HAVE_SCSI_SG_H
    sg_io_hdr_t io_hdr;

    C_PARAMS (port);

    /* The device needs to be opened for that operation */
    if (port->pl->fd == -1)
        CHECK (gp_port_usbscsi_open (port))

        memset(sense, 0, sense_size);
    memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
    if (to_dev) {
        io_hdr.dxfer_direction = SG_DXFER_TO_DEV;
    } else {
        memset (data, 0, data_size);
        io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
    }
    io_hdr.interface_id = 'S';
    io_hdr.cmdp = (unsigned char *)cmd;
    io_hdr.cmd_len = cmd_size;
    io_hdr.sbp = (unsigned char *)sense;
    io_hdr.mx_sb_len = sense_size;
    io_hdr.dxferp = (unsigned char *)data;
    io_hdr.dxfer_len = data_size;
    /*io_hdr.timeout = 1500;*/
    io_hdr.timeout = port->timeout;
    GP_LOG_D ("setting scsi command timeout to %d", port->timeout);
    if (io_hdr.timeout < 1500)
        io_hdr.timeout = 1500;

    if (ioctl (port->pl->fd, SG_IO, &io_hdr) < 0)
    {
        gp_port_set_error (port, _("Could not send scsi command to: "
                                   "'%s' (%m)."), port->settings.usbscsi.path);
        return GP_ERROR_IO;
    }
    return GP_OK;
#else
    return GP_ERROR_NOT_SUPPORTED;
#endif
}
Пример #21
0
/**
 * \brief Set port settings
 * \param port a #GPPort
 * \param settings the #GPPortSettings to be set
 *
 * Adjusts the settings of a port. You should always call
 * #gp_port_get_settings, adjust the values depending on the type of the port,
 * and then call #gp_port_set_settings.
 *
 * \return a gphoto2 error code
 **/
int
gp_port_set_settings (GPPort *port, GPPortSettings settings)
{
	GP_LOG_D ("Setting settings...");

	C_PARAMS (port);
	CHECK_INIT (port);

        /*
	 * We copy the settings to settings_pending and call update on the 
	 * port.
	 */
        memcpy (&port->settings_pending, &settings,
		sizeof (port->settings_pending));
	CHECK_SUPP (port, "update", port->pc->ops->update);
        CHECK_RESULT (port->pc->ops->update (port));

        return (GP_OK);
}
Пример #22
0
/**
 * \brief Print a message to the context
 *
 * This sends a message to the passed context, to be printed by
 * it in some kind of way, but do no other action.
 * 
 * To be used by camera drivers.
 *
 * \param context A GPContext
 * \param format A sprintf style format string
 * \param ... variable argument list depending on format string
 */
void
gp_context_message (GPContext *context, const char *format, ...)
{
	va_list args;
	char *str;

	va_start (args, format);
	str = gpi_vsnprintf(format, args);
	va_end (args);

	if (!str)
		return;

	/* Log the message */
	GP_LOG_D ("%s", str);

	if (context && context->message_func)
		context->message_func (context, str, context->message_func_data);
	free (str);
}
Пример #23
0
int
gp_camera_set_port_info (Camera *camera, GPPortInfo info)
{
	char	*name, *path;
	C_PARAMS (camera);

	/*
	 * If the camera is currently initialized, terminate that connection.
	 * We don't care if we are successful or not.
	 */
	if (camera->pc->lh)
		gp_camera_exit (camera, NULL);

	gp_port_info_get_name (info, &name);
	gp_port_info_get_path (info, &path);
	GP_LOG_D ("Setting port info for port '%s' at '%s'...", name, path);
	CR (camera, gp_port_set_info (camera->port, info), NULL);

	return (GP_OK);
}
Пример #24
0
/**
 * Free the \c camera.
 *
 * @param camera a #Camera
 * @return a gphoto2 error code
 *
 * \deprecated 
 * This function should never be used. Please use #gp_camera_unref instead.
 *
 */
int
gp_camera_free (Camera *camera)
{
	C_PARAMS (camera);

	GP_LOG_D ("Freeing camera...");

	/*
	 * If the camera is currently initialized, close the connection.
	 * We don't care if we are successful or not.
	 */
	if (camera->port && camera->pc && camera->pc->lh)
		gp_camera_exit (camera, NULL);

	/* We don't care if anything goes wrong */
	if (camera->port) {
		gp_port_free (camera->port);
		camera->port = NULL;
	}

	if (camera->pc) {
		free (camera->pc->timeout_ids);
		free (camera->pc);
		camera->pc = NULL;
	}

	if (camera->fs) {
		gp_filesystem_free (camera->fs);
		camera->fs = NULL;
	}

        if (camera->functions) {
                free (camera->functions);
		camera->functions = NULL;
	}
 
	free (camera);

	return (GP_OK);
}
Пример #25
0
/**
 * \brief Free the port structure
 * \param port a #GPPort
 *
 * Closes the port and frees the memory.
 *
 * \return a gphoto2 error code
 **/
int
gp_port_free (GPPort *port)
{
	GP_LOG_D ("Freeing port...");

	C_PARAMS (port);

	if (port->pc) {
		if (port->pc->ops) {

			/* We don't care for return values */
			gp_port_close (port);
			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
			port->pc->lh = NULL;
		}

		free (port->pc->info.name);
		free (port->pc->info.path);
		free (port->pc->info.library_filename);

		free (port->pc);
		port->pc = NULL;
	}

        free (port);

        return GP_OK;
}
Пример #26
0
/**
 * \brief Set specified serial PIN to value
 *
 * \param port a GPPort
 * \param pin the serial pin to be retrieved
 * \param level the setting of the pin
 *
 * Pulls the specified pin of a serial port to the specified level.
 *
 * \return a gphoto2 error code
 */
int
gp_port_set_pin (GPPort *port, GPPin pin, GPLevel level)
{
	unsigned int i, j;

	for (i = 0; PinTable[i].description_short; i++)
		if (PinTable[i].pin == pin)
			break;
	for (j = 0; LevelTable[j].description; j++)
		if (LevelTable[j].level == level)
			break;
	GP_LOG_D ("Setting pin %i (%s: '%s') to '%s'...",
		PinTable[i].number, PinTable[i].description_short,
		PinTable[i].description_long, _(LevelTable[j].description));

	C_PARAMS (port);
	CHECK_INIT (port);

	CHECK_SUPP (port, "set_pin", port->pc->ops->set_pin);
	CHECK_RESULT (port->pc->ops->set_pin (port, pin, level));

	return (GP_OK);
}
Пример #27
0
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;
}
Пример #28
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;
}
Пример #29
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;
}
Пример #30
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_libusb1_match_mtp_device(struct libusb_device *dev,int *configno, int *interfaceno, int *altsettingno)
{
	/* Marcus: Avoid this probing altogether, its too unstable on some devices */
	return 0;

#if 0
	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 ((desc.bDeviceClass!=0xff) && (desc.bDeviceClass!=0))
		return 0;
#endif
	if (dev->config) {
		xifaces = xnocamifaces = 0;
		for (i = 0; i < desc.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 == LIBUSB_CLASS_HID)	||
						(intf->bInterfaceClass == LIBUSB_CLASS_PRINTER)	||
						(intf->bInterfaceClass == LIBUSB_CLASS_AUDIO)	||
						(intf->bInterfaceClass == LIBUSB_CLASS_HUB)	||
						(intf->bInterfaceClass == LIBUSB_CLASS_COMM)	||
						(intf->bInterfaceClass == 0xe0)	/* wireless/bluetooth*/
					)
						xnocamifaces++;
				}
			}
		}
	}
	if (xifaces == xnocamifaces) /* only non-camera ifaces */
		return 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).
	 */
	if (dev->config) {
		for (i = 0; i < desc.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_D ("Configuration %d, interface %d, altsetting %d:\n", i, j, k);
						GP_LOG_D ("   Interface description contains the string \"MTP\"\n");
						GP_LOG_D ("   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 (buf, ret, "get_MS_OSD");
	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|LIBUSB_REQUEST_TYPE_VENDOR, cmd, 0, 4, buf, sizeof(buf), 1000);
	if (ret == -1) {
		GP_LOG_E ("control message says %d\n", ret);
		goto errout;
	}
	if (buf[0] != 0x28) {
		GP_LOG_E ("ret is %d, buf[0] is %x\n", ret, buf[0]);
		goto errout;
	}
	if (ret > 0) GP_LOG_DATA (buf, ret, "get_MS_ExtDesc");
	if ((buf[0x12] != 'M') || (buf[0x13] != 'T') || (buf[0x14] != 'P')) {
		GP_LOG_E ("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|LIBUSB_REQUEST_TYPE_VENDOR, cmd, 0, 5, buf, sizeof(buf), 1000);
	if (ret == -1) goto errout;
	if (buf[0] != 0x28) {
		GP_LOG_E ("ret is %d, buf[0] is %x\n", ret, buf[0]);
		goto errout;
	}
	if (ret > 0) GP_LOG_DATA (buf, ret, "get_MS_ExtProp");
	if ((buf[0x12] != 'M') || (buf[0x13] != 'T') || (buf[0x14] != 'P')) {
		GP_LOG_E ("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 (desc.bNumConfigurations > 1)
		GP_LOG_E ("The device has %d configurations!\n", desc.bNumConfigurations);
	for (i = 0; i < desc.bNumConfigurations; i++) {
		struct usb_config_descriptor *config =
			&dev->config[i];

		if (config->bNumInterfaces > 1)
			GP_LOG_E ("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_E ("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
}