示例#1
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_DATA (cmd, cmd_size, "Sending scsi cmd:");
	if (to_dev && data_size)
		GP_LOG_DATA (data, data_size, "with scsi cmd data:");

	C_PARAMS (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_D ("scsi cmd result: %d", retval);

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

	if (!to_dev && data_size)
		GP_LOG_DATA (data, data_size, "scsi cmd data:");

	return retval;
}
示例#2
0
/**
 * \brief Send a USB control message with output data
 *
 * \param port a GPPort
 * \param request control request code
 * \param value control value
 * \param index control index
 * \param bytes pointer to data
 * \param size size of the data
 *
 * Sends a specific USB control command and write associated data.
 *
 * \return a gphoto2 error code
 */
int
gp_port_usb_msg_write (GPPort *port, int request, int value, int index,
	char *bytes, int size)
{
        int retval;

	GP_LOG_DATA (bytes, size, "Writing message (request=0x%x value=0x%x index=0x%x size=%i=0x%x):",
		     request, value, index, size, size);

	C_PARAMS (port);
	CHECK_INIT (port);

	CHECK_SUPP (port, "msg_write", port->pc->ops->msg_write);
        retval = port->pc->ops->msg_write(port, request, value, index, bytes, size);
	CHECK_RESULT (retval);

        return (retval);
}
示例#3
0
static void LIBUSB_CALL
_cb_irq(struct libusb_transfer *transfer)
{
	struct _GPPortPrivateLibrary *pl = transfer->user_data;
	int i;

	GP_LOG_D("%p with status %d", transfer, transfer->status);

	if (	(transfer->status == LIBUSB_TRANSFER_CANCELLED) ||
		(transfer->status == LIBUSB_TRANSFER_TIMED_OUT) || /* on close */
		(transfer->status == LIBUSB_TRANSFER_NO_DEVICE) /* on removing camera */
	) {
		/* Only requeue the global transfers, not temporary ones */
		for (i = 0; i < sizeof(pl->transfers)/sizeof(pl->transfers[0]); i++) {
			if (pl->transfers[i] == transfer) {
				libusb_free_transfer (transfer);
				pl->transfers[i] = NULL;
				return;
			}
		}
		return;
	}

	if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
		GP_LOG_D("transfer %p should be in LIBUSB_TRANSFER_COMPLETED, but is %d!", transfer, transfer->status);
		return;
	}
	if (transfer->actual_length) {
		GP_LOG_DATA ((char*)transfer->buffer, transfer->actual_length, "interrupt");

		pl->irqs 	= realloc(pl->irqs, sizeof(pl->irqs[0])*(pl->nrofirqs+1));
		pl->irqlens	= realloc(pl->irqlens, sizeof(pl->irqlens[0])*(pl->nrofirqs+1));

		pl->irqlens[pl->nrofirqs] = transfer->actual_length;
		pl->irqs[pl->nrofirqs] = malloc(transfer->actual_length);
		memcpy(pl->irqs[pl->nrofirqs],transfer->buffer,transfer->actual_length);
		pl->nrofirqs++;
	}

	GP_LOG_D("requeuing complete transfer %p", transfer);
	LOG_ON_LIBUSB_E(libusb_submit_transfer(transfer));
	return;
}
示例#4
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
}