Пример #1
0
FN_INTERNAL int fnusb_open_subdevices(freenect_device *dev, int index)
{
	freenect_context *ctx = dev->parent;

    dev->device_does_motor_control_with_audio = 0;
    dev->motor_control_with_audio_enabled = 0;
    
	dev->usb_cam.parent = dev;
	dev->usb_cam.dev = NULL;
	dev->usb_motor.parent = dev;
	dev->usb_motor.dev = NULL;
#ifdef BUILD_AUDIO
	dev->usb_audio.parent = dev;
	dev->usb_audio.dev = NULL;
#endif

	libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
	ssize_t cnt = libusb_get_device_list (dev->parent->usb.ctx, &devs); //get the list of devices
	if (cnt < 0)
		return -1;

	int i = 0, nr_cam = 0, nr_mot = 0;
#ifdef BUILD_AUDIO
	int nr_audio = 0;
#endif
	int res;
	struct libusb_device_descriptor desc;

	for (i = 0; i < cnt; i++) {
		int r = libusb_get_device_descriptor (devs[i], &desc);
		if (r < 0)
			continue;

		if (desc.idVendor != VID_MICROSOFT)
			continue;
		res = 0;
		// Search for the camera
		if ((ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA) && !dev->usb_cam.dev && (desc.idProduct == PID_NUI_CAMERA || desc.idProduct == PID_K4W_CAMERA)) {
			// If the index given by the user matches our camera index
			if (nr_cam == index) {
				res = libusb_open (devs[i], &dev->usb_cam.dev);
				if (res < 0 || !dev->usb_cam.dev) {
					FN_ERROR("Could not open camera: %d\n", res);
					dev->usb_cam.dev = NULL;
					break;
				}
				if(desc.idProduct == PID_K4W_CAMERA || desc.bcdDevice != fn_le32(267)){
					/* Not the old kinect so we only set up the camera*/ 
					ctx->enabled_subdevices = FREENECT_DEVICE_CAMERA;
					ctx->zero_plane_res = 334;
                    dev->device_does_motor_control_with_audio = 1;

                    //lets also set the LED ON
                    //this keeps the camera alive for some systems which get freezes
                    if( desc.idProduct == PID_K4W_CAMERA ){
                        freenect_extra_keep_alive(PID_K4W_AUDIO);
                    }else{
                        freenect_extra_keep_alive(PID_NUI_AUDIO);
                    }
                    
#ifdef BUILD_AUDIO
                    //for newer devices we need to enable the audio device for motor control
                    if( (ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO) == 0 ){
                        ctx->enabled_subdevices |= FREENECT_DEVICE_AUDIO;
                    }
#endif
                    
				}else{
					/* The good old kinect that tilts and tweets */
					ctx->zero_plane_res = 322;
				}
				
#ifndef _WIN32
				// Detach an existing kernel driver for the device
				res = libusb_kernel_driver_active(dev->usb_cam.dev, 0);
				if (res == 1) {
					res = libusb_detach_kernel_driver(dev->usb_cam.dev, 0);
					if (res < 0) {
						FN_ERROR("Could not detach kernel driver for camera: %d\n", res);
						libusb_close(dev->usb_cam.dev);
						dev->usb_cam.dev = NULL;
						break;
					}
				}
#endif
				res = libusb_claim_interface (dev->usb_cam.dev, 0);
				if (res < 0) {
					FN_ERROR("Could not claim interface on camera: %d\n", res);
					libusb_close(dev->usb_cam.dev);
					dev->usb_cam.dev = NULL;
					break;
				}
				if(desc.idProduct == PID_K4W_CAMERA){
					res = libusb_set_interface_alt_setting(dev->usb_cam.dev, 0, 1);
         				if (res != 0) {
           					FN_ERROR("Failed to set alternate interface #1 for K4W: %d\n", res);
           					libusb_close(dev->usb_cam.dev);
          					dev->usb_cam.dev = NULL;
           					break;
          				}
					
				}
			} else {
				nr_cam++;
			}
		}
	}
	
	if(ctx->enabled_subdevices == FREENECT_DEVICE_CAMERA || res < 0) cnt = 0;
	
		// Search for the motor
	
	for (i = 0; i < cnt; i++) {
		int r = libusb_get_device_descriptor (devs[i], &desc);
		if (r < 0)
			continue;

		if (desc.idVendor != VID_MICROSOFT)
			continue;
		if ((ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR) && !dev->usb_motor.dev && desc.idProduct == PID_NUI_MOTOR) {
			// If the index given by the user matches our camera index
			if (nr_mot == index) {
				res = libusb_open (devs[i], &dev->usb_motor.dev);
				if (res < 0 || !dev->usb_motor.dev) {
					FN_ERROR("Could not open motor: %d\n", res);
					dev->usb_motor.dev = NULL;
					break;
				}
				res = libusb_claim_interface (dev->usb_motor.dev, 0);
				if (res < 0) {
					FN_ERROR("Could not claim interface on motor: %d\n", res);
					libusb_close(dev->usb_motor.dev);
					dev->usb_motor.dev = NULL;
					break;
				}
			} else {
				nr_mot++;
			}
		}

#ifdef BUILD_AUDIO
		// TODO: check that the firmware has already been loaded; if not, upload firmware.
		// Search for the audio
		if ((ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO) && !dev->usb_audio.dev && (desc.idProduct == PID_NUI_AUDIO || fn_is_pid_k4w_audio(desc.idProduct) != -1 )) {
			// If the index given by the user matches our audio index
            
			if (nr_audio == index) {
				res = libusb_open (devs[i], &dev->usb_audio.dev);
				if (res < 0 || !dev->usb_audio.dev) {
					FN_ERROR("Could not open audio: %d\n", res);
					dev->usb_audio.dev = NULL;
					break;
				}
				res = libusb_claim_interface (dev->usb_audio.dev, 0);
				if (res < 0) {
					FN_ERROR("Could not claim interface on audio: %d\n", res);
					libusb_close(dev->usb_audio.dev);
					dev->usb_audio.dev = NULL;
					break;
				}
                
				// Using the device handle that we've claimed, see if this
				// device has already uploaded firmware (has 2 interfaces).  If
				// not, save the serial number (by reading the appropriate
				// descriptor), upload the firmware, and then enter a loop
				// waiting for a device with the same serial number to
				// reappear.
				int num_interfaces = fnusb_num_interfaces(&dev->usb_audio);
                
                if( num_interfaces >= 2 ){
                    if( dev->device_does_motor_control_with_audio ){
                        dev->motor_control_with_audio_enabled = 1;
                    }
                }else{
                
					// Read the serial number from the string descriptor and save it.
					unsigned char string_desc[256]; // String descriptors are at most 256 bytes
					res = libusb_get_string_descriptor_ascii(dev->usb_audio.dev, desc.iSerialNumber, string_desc, 256);
					if (res < 0) {
						FN_ERROR("Failed to retrieve serial number for audio device in bootloader state\n");
						break;
					}
					char* audio_serial = strdup((char*)string_desc);
                
					FN_SPEW("Uploading firmware to audio device in bootloader state.\n");
                    
                    // Check if we can load from memory - otherwise load from disk 
                    if( desc.idProduct == PID_NUI_AUDIO && ctx->fn_fw_nui_ptr && ctx->fn_fw_nui_size > 0){
                        FN_SPEW("loading firmware from memory\n");
                        res = upload_firmware_from_memory(&dev->usb_audio, ctx->fn_fw_nui_ptr, ctx->fn_fw_nui_size);
                    }
                    else if( desc.idProduct == PID_K4W_AUDIO && ctx->fn_fw_k4w_ptr && ctx->fn_fw_k4w_size > 0 ){
                        FN_SPEW("loading firmware from memory\n");
                        res = upload_firmware_from_memory(&dev->usb_audio, ctx->fn_fw_k4w_ptr, ctx->fn_fw_k4w_size);
                    }
                    else{
                        res = upload_firmware(&dev->usb_audio, "audios.bin");
                    }
					
                    if (res < 0) {
						FN_ERROR("upload_firmware failed: %d\n", res);
						break;
					}
					libusb_close(dev->usb_audio.dev);
					dev->usb_audio.dev = NULL;
					// Wait for the device to reappear.
					int loops = 0;
					for (loops = 0; loops < 10; loops++) { // Loop for at most 10 tries.
						FN_SPEW("Try %d: Looking for new audio device matching serial %s\n", loops, audio_serial);
						// Scan devices.
						libusb_device **new_dev_list;
						int dev_index;
						ssize_t num_new_devs = libusb_get_device_list(ctx->usb.ctx, &new_dev_list);
						for (dev_index = 0; dev_index < num_new_devs; ++dev_index) {
							struct libusb_device_descriptor new_dev_desc;
							int r;
							r = libusb_get_device_descriptor (new_dev_list[dev_index], &new_dev_desc);
							if (r < 0)
								continue;
							// If this dev is a Kinect audio device, open device, read serial, and compare.
							if (new_dev_desc.idVendor == VID_MICROSOFT && (new_dev_desc.idProduct == PID_NUI_AUDIO || fn_is_pid_k4w_audio(desc.idProduct) != -1) ){
								FN_SPEW("Matched VID/PID!\n");
								libusb_device_handle* new_dev_handle;
								// Open device
								r = libusb_open(new_dev_list[dev_index], &new_dev_handle);
								if (r < 0)
									continue;
								// Read serial
								r = libusb_get_string_descriptor_ascii(new_dev_handle, new_dev_desc.iSerialNumber, string_desc, 256);
								if (r < 0) {
									FN_SPEW("Lost new audio device while fetching serial number.\n");
									libusb_close(new_dev_handle);
									continue;
								}
								// Compare to expected serial
								if (r == strlen(audio_serial) && strcmp((char*)string_desc, audio_serial) == 0) {
									// We found it!
									r = libusb_claim_interface(new_dev_handle, 0);
									if (r != 0) {
										// Ouch, found the device but couldn't claim the interface.
										FN_SPEW("Device with serial %s reappeared but couldn't claim interface 0\n", audio_serial);
										libusb_close(new_dev_handle);
										continue;
									}
									// Save the device handle.
									dev->usb_audio.dev = new_dev_handle;
									
                                    // Verify that we've actually found a device running the right firmware.
									num_interfaces = fnusb_num_interfaces(&dev->usb_audio);
                                    
                                    if( num_interfaces >= 2 ){
                                        if( dev->device_does_motor_control_with_audio ){
                                            dev->motor_control_with_audio_enabled = 1;
                                        }
                                    }else{
                                        FN_SPEW("Opened audio with matching serial but too few interfaces.\n");
										dev->usb_audio.dev = NULL;
										libusb_close(new_dev_handle);
										continue;
									}									break;
								} else {
									FN_SPEW("Got serial %s, expected serial %s\n", (char*)string_desc, audio_serial);
								}
							}
						}

						libusb_free_device_list(new_dev_list, 1);
						// If we found the right device, break out of this loop.
						if (dev->usb_audio.dev)
							break;
						// Sleep for a second to give the device more time to reenumerate.
						sleep(1);
					}
					free(audio_serial);
				}
			} else {
				nr_audio++;
			}
		}
#endif

	}

	libusb_free_device_list (devs, 1);  // free the list, unref the devices in it

	// Check that each subdevice is either opened or not enabled.
	if ( (dev->usb_cam.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA))
		&& (dev->usb_motor.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR))
#ifdef BUILD_AUDIO
		&& (dev->usb_audio.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO))
#endif
		) {
		return 0;
	} else {
		if (dev->usb_cam.dev) {
			libusb_release_interface(dev->usb_cam.dev, 0);
			libusb_close(dev->usb_cam.dev);
		} else {
			FN_ERROR("Failed to open camera subdevice or it is not disabled.");
		}

		if (dev->usb_motor.dev) {
			libusb_release_interface(dev->usb_motor.dev, 0);
			libusb_close(dev->usb_motor.dev);
		} else {
			FN_ERROR("Failed to open motor subddevice or it is not disabled.");
		}

#ifdef BUILD_AUDIO
		if (dev->usb_audio.dev) {
			libusb_release_interface(dev->usb_audio.dev, 0);
			libusb_close(dev->usb_audio.dev);
		} else {
			FN_ERROR("Failed to open audio subdevice or it is not disabled.");
		}
#endif
		return -1;
	}
}
Пример #2
0
int main(int argc, char **argv)
{
	int expected_size = 0;
	unsigned int transfer_size = 0;
	enum mode mode = MODE_NONE;
	struct dfu_status status;
	libusb_context *ctx;
	struct dfu_file file;
	char *end;
	int final_reset = 0;
	int ret;
	int dfuse_device = 0;
	int fd;
	const char *dfuse_options = NULL;
	int detach_delay = 5;
	int dfu_has_suffix = 1;
	uint16_t runtime_vendor;
	uint16_t runtime_product;

	memset(&file, 0, sizeof(file));

	/* make sure all prints are flushed */
	setvbuf(stdout, NULL, _IONBF, 0);

	while (1) {
		int c, option_index = 0;
		c = getopt_long(argc, argv, "hVvleE:d:p:c:i:a:S:t:U:D:Rs:Z:", opts,
				&option_index);
		if (c == -1)
			break;

		switch (c) {
		case 'h':
			help();
			break;
		case 'V':
			mode = MODE_VERSION;
			break;
		case 'v':
			verbose++;
			break;
		case 'l':
			mode = MODE_LIST;
			break;
		case 'e':
			mode = MODE_DETACH;
			match_iface_alt_index = 0;
			match_iface_index = 0;
			break;
		case 'E':
			detach_delay = atoi(optarg);
			break;
		case 'd':
			parse_vendprod(optarg);
			break;
		case 'p':
			/* Parse device path */
			ret = resolve_device_path(optarg);
			if (ret < 0)
				errx(EX_SOFTWARE, "Unable to parse '%s'", optarg);
			if (!ret)
				errx(EX_SOFTWARE, "Cannot find '%s'", optarg);
			break;
		case 'c':
			/* Configuration */
			match_config_index = atoi(optarg);
			break;
		case 'i':
			/* Interface */
			match_iface_index = atoi(optarg);
			break;
		case 'a':
			/* Interface Alternate Setting */
			match_iface_alt_index = strtoul(optarg, &end, 0);
			if (*end) {
				match_iface_alt_name = optarg;
				match_iface_alt_index = -1;
			}
			break;
		case 'S':
			parse_serial(optarg);
			break;
		case 't':
			transfer_size = atoi(optarg);
			break;
		case 'U':
			mode = MODE_UPLOAD;
			file.name = optarg;
			break;
		case 'Z':
			expected_size = atoi(optarg);
			break;
		case 'D':
			mode = MODE_DOWNLOAD;
			file.name = optarg;
			break;
		case 'R':
			final_reset = 1;
			break;
		case 's':
			dfuse_options = optarg;
			dfu_has_suffix = 0;
			break;
		default:
			help();
			break;
		}
	}

	print_version();
	if (mode == MODE_VERSION) {
		exit(0);
	}

	if (mode == MODE_NONE) {
		fprintf(stderr, "You need to specify one of -D or -U\n");
		help();
	}

	if (mode == MODE_DOWNLOAD) {
		dfu_load_file(&file, dfu_has_suffix, 0);
		/* If the user didn't specify product and/or vendor IDs to match,
		 * use any IDs from the file suffix for device matching */
		if (match_vendor < 0 && file.idVendor != 0xffff) {
			match_vendor = file.idVendor;
			printf("Match vendor ID from file: %04x\n", match_vendor);
		}
		if (match_product < 0 && file.idProduct != 0xffff) {
			match_product = file.idProduct;
			printf("Match product ID from file: %04x\n", match_product);
		}
	}

	ret = libusb_init(&ctx);
	if (ret)
		errx(EX_IOERR, "unable to initialize libusb: %i", ret);

	if (verbose > 2) {
		libusb_set_debug(ctx, 255);
	}

	probe_devices(ctx);

	if (mode == MODE_LIST) {
		list_dfu_interfaces();
		exit(0);
	}

	if (dfu_root == NULL) {
		errx(EX_IOERR, "No DFU capable USB device found");
	} else if (dfu_root->next != NULL) {
		/* We cannot safely support more than one DFU capable device
		 * with same vendor/product ID, since during DFU we need to do
		 * a USB bus reset, after which the target device will get a
		 * new address */
		errx(EX_IOERR, "More than one DFU capable USB device found! "
		       "Try `--list' and specify the serial number "
		       "or disconnect all but one device\n");
	}

	/* We have exactly one device. Its libusb_device is now in dfu_root->dev */

	printf("Opening DFU capable USB device...\n");
	ret = libusb_open(dfu_root->dev, &dfu_root->dev_handle);
	if (ret || !dfu_root->dev_handle)
		errx(EX_IOERR, "Cannot open device");

	printf("ID %04x:%04x\n", dfu_root->vendor, dfu_root->product);

	printf("Run-time device DFU version %04x\n",
	       libusb_le16_to_cpu(dfu_root->func_dfu.bcdDFUVersion));

	/* Transition from run-Time mode to DFU mode */
	if (!(dfu_root->flags & DFU_IFF_DFU)) {
		int err;
		/* In the 'first round' during runtime mode, there can only be one
		* DFU Interface descriptor according to the DFU Spec. */

		/* FIXME: check if the selected device really has only one */

		runtime_vendor = dfu_root->vendor;
		runtime_product = dfu_root->product;

		printf("Claiming USB DFU Runtime Interface...\n");
		if (libusb_claim_interface(dfu_root->dev_handle, dfu_root->interface) < 0) {
			errx(EX_IOERR, "Cannot claim interface %d",
				dfu_root->interface);
		}

		if (libusb_set_interface_alt_setting(dfu_root->dev_handle, dfu_root->interface, 0) < 0) {
			errx(EX_IOERR, "Cannot set alt interface zero");
		}

		printf("Determining device status: ");

		err = dfu_get_status(dfu_root->dev_handle, dfu_root->interface, &status);
		if (err == LIBUSB_ERROR_PIPE) {
			printf("Device does not implement get_status, assuming appIDLE\n");
			status.bStatus = DFU_STATUS_OK;
			status.bwPollTimeout = 0;
			status.bState  = DFU_STATE_appIDLE;
			status.iString = 0;
		} else if (err < 0) {
			errx(EX_IOERR, "error get_status");
		} else {
			printf("state = %s, status = %d\n",
			       dfu_state_to_string(status.bState), status.bStatus);
		}

		if (!(dfu_root->quirks & QUIRK_POLLTIMEOUT))
			milli_sleep(status.bwPollTimeout);

		switch (status.bState) {
		case DFU_STATE_appIDLE:
		case DFU_STATE_appDETACH:
			printf("Device really in Runtime Mode, send DFU "
			       "detach request...\n");
			if (dfu_detach(dfu_root->dev_handle,
				       dfu_root->interface, 1000) < 0) {
				errx(EX_IOERR, "error detaching");
			}
			libusb_release_interface(dfu_root->dev_handle,
						 dfu_root->interface);
			if (dfu_root->func_dfu.bmAttributes & USB_DFU_WILL_DETACH) {
				printf("Device will detach and reattach...\n");
			} else {
				printf("Resetting USB...\n");
				ret = libusb_reset_device(dfu_root->dev_handle);
				if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND)
					errx(EX_IOERR, "error resetting "
						"after detach");
			}
			break;
		case DFU_STATE_dfuERROR:
			printf("dfuERROR, clearing status\n");
			if (dfu_clear_status(dfu_root->dev_handle,
					     dfu_root->interface) < 0) {
				errx(EX_IOERR, "error clear_status");
			}
			/* fall through */
		default:
			warnx("WARNING: Runtime device already in DFU state ?!?");
			goto dfustate;
			break;
		}
		libusb_release_interface(dfu_root->dev_handle,
					 dfu_root->interface);
		libusb_close(dfu_root->dev_handle);
		dfu_root->dev_handle = NULL;

		if (mode == MODE_DETACH) {
			libusb_exit(ctx);
			exit(0);
		}

		/* keeping handles open might prevent re-enumeration */
		disconnect_devices();

		milli_sleep(detach_delay * 1000);

		/* Change match vendor and product to impossible values to force
		 * only DFU mode matches in the following probe */
		match_vendor = match_product = 0x10000;

		probe_devices(ctx);

		if (dfu_root == NULL) {
			errx(EX_IOERR, "Lost device after RESET?");
		} else if (dfu_root->next != NULL) {
			errx(EX_IOERR, "More than one DFU capable USB device found! "
				"Try `--list' and specify the serial number "
				"or disconnect all but one device");
		}

		/* Check for DFU mode device */
		if (!(dfu_root->flags | DFU_IFF_DFU))
			errx(EX_SOFTWARE, "Device is not in DFU mode");

		printf("Opening DFU USB Device...\n");
		ret = libusb_open(dfu_root->dev, &dfu_root->dev_handle);
		if (ret || !dfu_root->dev_handle) {
			errx(EX_IOERR, "Cannot open device");
		}
	} else {
		/* we're already in DFU mode, so we can skip the detach/reset
		 * procedure */
		/* If a match vendor/product was specified, use that as the runtime
		 * vendor/product, otherwise use the DFU mode vendor/product */
		runtime_vendor = match_vendor < 0 ? dfu_root->vendor : match_vendor;
		runtime_product = match_product < 0 ? dfu_root->product : match_product;
	}

dfustate:
#if 0
	printf("Setting Configuration %u...\n", dfu_root->configuration);
	if (libusb_set_configuration(dfu_root->dev_handle, dfu_root->configuration) < 0) {
		errx(EX_IOERR, "Cannot set configuration");
	}
#endif
	printf("Claiming USB DFU Interface...\n");
	if (libusb_claim_interface(dfu_root->dev_handle, dfu_root->interface) < 0) {
		errx(EX_IOERR, "Cannot claim interface");
	}

	printf("Setting Alternate Setting #%d ...\n", dfu_root->altsetting);
	if (libusb_set_interface_alt_setting(dfu_root->dev_handle, dfu_root->interface, dfu_root->altsetting) < 0) {
		errx(EX_IOERR, "Cannot set alternate interface");
	}

status_again:
	printf("Determining device status: ");
	if (dfu_get_status(dfu_root->dev_handle, dfu_root->interface, &status ) < 0) {
		errx(EX_IOERR, "error get_status");
	}
	printf("state = %s, status = %d\n",
	       dfu_state_to_string(status.bState), status.bStatus);
	if (!(dfu_root->quirks & QUIRK_POLLTIMEOUT))
		milli_sleep(status.bwPollTimeout);

	switch (status.bState) {
	case DFU_STATE_appIDLE:
	case DFU_STATE_appDETACH:
		errx(EX_IOERR, "Device still in Runtime Mode!");
		break;
	case DFU_STATE_dfuERROR:
		printf("dfuERROR, clearing status\n");
		if (dfu_clear_status(dfu_root->dev_handle, dfu_root->interface) < 0) {
			errx(EX_IOERR, "error clear_status");
		}
		goto status_again;
		break;
	case DFU_STATE_dfuDNLOAD_IDLE:
	case DFU_STATE_dfuUPLOAD_IDLE:
		printf("aborting previous incomplete transfer\n");
		if (dfu_abort(dfu_root->dev_handle, dfu_root->interface) < 0) {
			errx(EX_IOERR, "can't send DFU_ABORT");
		}
		goto status_again;
		break;
	case DFU_STATE_dfuIDLE:
		printf("dfuIDLE, continuing\n");
		break;
	default:
		break;
	}

	if (DFU_STATUS_OK != status.bStatus ) {
		printf("WARNING: DFU Status: '%s'\n",
			dfu_status_to_string(status.bStatus));
		/* Clear our status & try again. */
		if (dfu_clear_status(dfu_root->dev_handle, dfu_root->interface) < 0)
			errx(EX_IOERR, "USB communication error");
		if (dfu_get_status(dfu_root->dev_handle, dfu_root->interface, &status) < 0)
			errx(EX_IOERR, "USB communication error");
		if (DFU_STATUS_OK != status.bStatus)
			errx(EX_SOFTWARE, "Status is not OK: %d", status.bStatus);
		if (!(dfu_root->quirks & QUIRK_POLLTIMEOUT))
			milli_sleep(status.bwPollTimeout);
	}

	printf("DFU mode device DFU version %04x\n",
	       libusb_le16_to_cpu(dfu_root->func_dfu.bcdDFUVersion));

	if (dfu_root->func_dfu.bcdDFUVersion == libusb_cpu_to_le16(0x11a))
		dfuse_device = 1;

	/* If not overridden by the user */
	if (!transfer_size) {
		transfer_size = libusb_le16_to_cpu(
		    dfu_root->func_dfu.wTransferSize);
		if (transfer_size) {
			printf("Device returned transfer size %i\n",
			       transfer_size);
		} else {
			errx(EX_IOERR, "Transfer size must be "
				"specified");
		}
	}

#ifdef HAVE_GETPAGESIZE
/* autotools lie when cross-compiling for Windows using mingw32/64 */
#ifndef __MINGW32__
	/* limitation of Linux usbdevio */
	if ((int)transfer_size > getpagesize()) {
		transfer_size = getpagesize();
		printf("Limited transfer size to %i\n", transfer_size);
	}
#endif /* __MINGW32__ */
#endif /* HAVE_GETPAGESIZE */

	if (transfer_size < dfu_root->bMaxPacketSize0) {
		transfer_size = dfu_root->bMaxPacketSize0;
		printf("Adjusted transfer size to %i\n", transfer_size);
	}

	switch (mode) {
	case MODE_UPLOAD:
		/* open for "exclusive" writing */
		fd = open(file.name, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0666);
		if (fd < 0)
			err(EX_IOERR, "Cannot open file %s for writing", file.name);

		if (dfuse_device || dfuse_options) {
		    if (dfuse_do_upload(dfu_root, transfer_size, fd,
					dfuse_options) < 0)
			exit(1);
		} else {
		    if (dfuload_do_upload(dfu_root, transfer_size,
			expected_size, fd) < 0) {
			exit(1);
		    }
		}
		close(fd);
		break;

	case MODE_DOWNLOAD:
		if (((file.idVendor  != 0xffff && file.idVendor  != runtime_vendor) ||
		     (file.idProduct != 0xffff && file.idProduct != runtime_product)) &&
		    ((file.idVendor  != 0xffff && file.idVendor  != dfu_root->vendor) ||
		     (file.idProduct != 0xffff && file.idProduct != dfu_root->product))) {
			errx(EX_IOERR, "Error: File ID %04x:%04x does "
				"not match device (%04x:%04x or %04x:%04x)",
				file.idVendor, file.idProduct,
				runtime_vendor, runtime_product,
				dfu_root->vendor, dfu_root->product);
		}
		if (dfuse_device || dfuse_options || file.bcdDFU == 0x11a) {
		        if (dfuse_do_dnload(dfu_root, transfer_size, &file,
							dfuse_options) < 0)
				exit(1);
		} else {
			if (dfuload_do_dnload(dfu_root, transfer_size, &file) < 0)
				exit(1);
	 	}
		break;
	case MODE_DETACH:
		if (dfu_detach(dfu_root->dev_handle, dfu_root->interface, 1000) < 0) {
			errx(EX_IOERR, "can't detach");
		}
		break;
	default:
		errx(EX_IOERR, "Unsupported mode: %u", mode);
		break;
	}

	if (final_reset) {
		if (dfu_detach(dfu_root->dev_handle, dfu_root->interface, 1000) < 0) {
			errx(EX_IOERR, "can't detach");
		}
		printf("Resetting USB to switch back to runtime mode\n");
		ret = libusb_reset_device(dfu_root->dev_handle);
		if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND) {
			errx(EX_IOERR, "error resetting after download");
		}
	}

	libusb_close(dfu_root->dev_handle);
	dfu_root->dev_handle = NULL;
	libusb_exit(ctx);

	return (0);
}
Пример #3
0
static struct usb_device_info * usb_device_is_valid(struct libusb_device * dev) {

	int err, i;
	char product[1024];
	libusb_device_handle * udev;
	struct usb_device_info * ret = NULL;
	struct libusb_device_descriptor desc;

	if ( libusb_get_device_descriptor(dev, &desc) < 0 ) {
		PRINTF_LINE("libusb_get_device_descriptor failed");
		PRINTF_END();
		return NULL;
	}

	for ( i = 0; usb_devices[i].vendor; ++i ) {

		if ( desc.idVendor == usb_devices[i].vendor && desc.idProduct == usb_devices[i].product ) {

			printf("\b\b  ");
			PRINTF_END();
			PRINTF_ADD("Found ");
			usb_flash_device_info_print(&usb_devices[i]);
			PRINTF_END();

			PRINTF_LINE("Opening USB...");

			err = libusb_open(dev, &udev);
			if ( err < 0 ) {
				PRINTF_ERROR("libusb_open failed");
				fprintf(stderr, "\n");
				return NULL;
			}

			usb_descriptor_info_print(udev, dev, product, sizeof(product));

			if ( usb_devices[i].interface >= 0 ) {

				PRINTF_LINE("Detaching kernel from USB interface...");
				libusb_detach_kernel_driver(udev, usb_devices[i].interface);

				PRINTF_LINE("Claiming USB interface...");
				if ( libusb_claim_interface(udev, usb_devices[i].interface) < 0 ) {
					PRINTF_ERROR("libusb_claim_interface failed");
					fprintf(stderr, "\n");
					usb_reattach_kernel_driver(udev, usb_devices[i].interface);
					libusb_close(udev);
					return NULL;
				}

			}

			if ( usb_devices[i].alternate >= 0 ) {
				PRINTF_LINE("Setting alternate USB interface...");
				if ( libusb_set_interface_alt_setting(udev, usb_devices[i].interface, usb_devices[i].alternate) < 0 ) {
					PRINTF_ERROR("libusb_claim_interface failed");
					fprintf(stderr, "\n");
					usb_reattach_kernel_driver(udev, usb_devices[i].interface);
					libusb_close(udev);
					return NULL;
				}
			}

			if ( usb_devices[i].configuration >= 0 ) {
				PRINTF_LINE("Setting USB configuration...");
				if ( libusb_set_configuration(udev, usb_devices[i].configuration) < 0 ) {
					PRINTF_ERROR("libusb_set_configuration failed");
					fprintf(stderr, "\n");
					usb_reattach_kernel_driver(udev, usb_devices[i].interface);
					libusb_close(udev);
					return NULL;
				}
			}

			ret = calloc(1, sizeof(struct usb_device_info));
			if ( ! ret ) {
				ALLOC_ERROR();
				usb_reattach_kernel_driver(udev, usb_devices[i].interface);
				libusb_close(udev);
				return NULL;
			}

			if ( strstr(product, "N900") )
				ret->device = DEVICE_RX_51;
			else if ( strstr(product, "N950") )
				ret->device = DEVICE_RM_680;
			else
				ret->device = DEVICE_UNKNOWN;

			/* TODO: Autodetect more devices */

			if ( device_to_string(ret->device) )
				PRINTF_LINE("Detected USB device: %s", device_to_string(ret->device));
			else
				PRINTF_LINE("Detected USB device: (not detected)");
			PRINTF_END();

			if ( ret->device ) {
				enum device * device;
				for ( device = usb_devices[i].devices; *device; ++device )
					if ( *device == ret->device )
						break;
				if ( ! *device ) {
					ERROR("Device mishmash");
					fprintf(stderr, "\n");
					usb_reattach_kernel_driver(udev, usb_devices[i].interface);
					libusb_close(udev);
					free(ret);
					return NULL;
				}
			}

			ret->hwrev = -1;
			ret->flash_device = &usb_devices[i];
			ret->udev = udev;
			break;
		}
	}

	return ret;

}
Пример #4
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;

	if (!port)
		return GP_ERROR_BAD_PARAMETERS;

	gp_log (GP_LOG_DEBUG, "libusb1", "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
	);

/* do not set it here, otherwise stv680 doesnt work 
	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)
		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, "libusb1", "changing interface %d -> %d",
			port->pl->interface,
			port->settings.usb.interface
		);
		if (libusb_release_interface (port->pl->dh,
					   port->pl->interface) < 0) {
			gp_log (GP_LOG_DEBUG, "libusb1","releasing the iface for config failed.");
			/* Not a hard error for now. -Marcus */
		} else {
			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) {
				gp_log (GP_LOG_DEBUG, "libusb1","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, "libusb1", "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 (libusb_release_interface (port->pl->dh,
					   port->settings.usb.interface) < 0) {
			gp_log (GP_LOG_DEBUG, "libusb1","releasing the iface for config failed.");
			ifacereleased = FALSE;
		} else {
			ifacereleased = TRUE;
		}
		ret = libusb_set_configuration(port->pl->dh,
				     port->settings.usb.config);
		if (ret < 0) {
#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 (GP_LOG_ERROR, "libusb1","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, "libusb1",
			"Changed usb.config from %d to %d",
			port->pl->config,
			port->settings.usb.config);

		if (ifacereleased) {
			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) {
				gp_log (GP_LOG_DEBUG, "libusb1","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 = libusb_set_interface_alt_setting (
			port->pl->dh,
			port->settings.usb.interface, 
			port->settings.usb.altsetting
		);
		if (ret < 0) {
			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 (GP_LOG_DEBUG, "libusb1",
			"Changed usb.altsetting from %d to %d",
			port->pl->altsetting,
			port->settings.usb.altsetting);
		port->pl->altsetting = port->settings.usb.altsetting;
	}

	return GP_OK;
}
static int prepare_device(libusb_device_handle * aHandle){

    int r;
    int kernel_driver_detached = 0;

    // Detach OS driver (not possible for OS X and WIN32)
#if !defined(__APPLE__) && !defined(_WIN32)
    r = libusb_kernel_driver_active(aHandle, 0);
    if (r < 0) {
        log_error("libusb_kernel_driver_active error %d", r);
        libusb_close(aHandle);
        return r;
    }

    if (r == 1) {
        r = libusb_detach_kernel_driver(aHandle, 0);
        if (r < 0) {
            log_error("libusb_detach_kernel_driver error %d", r);
            libusb_close(aHandle);
            return r;
        }
        kernel_driver_detached = 1;
    }
    log_info("libusb_detach_kernel_driver");
#endif

    const int configuration = 1;
    log_info("setting configuration %d...", configuration);
    r = libusb_set_configuration(aHandle, configuration);
    if (r < 0) {
        log_error("Error libusb_set_configuration: %d", r);
        if (kernel_driver_detached){
            libusb_attach_kernel_driver(aHandle, 0);
        }
        libusb_close(aHandle);
        return r;
    }

    // reserve access to device
    log_info("claiming interface 0...");
    r = libusb_claim_interface(aHandle, 0);
    if (r < 0) {
        log_error("Error claiming interface %d", r);
        if (kernel_driver_detached){
            libusb_attach_kernel_driver(aHandle, 0);
        }
        libusb_close(aHandle);
        return r;
    }

#ifdef HAVE_SCO
    log_info("claiming interface 1...");
    r = libusb_claim_interface(aHandle, 1);
    if (r < 0) {
        log_error("Error claiming interface %d", r);
        if (kernel_driver_detached){
            libusb_attach_kernel_driver(aHandle, 0);
        }
        libusb_close(aHandle);
        return r;
    }
    log_info("Switching to setting %u on interface 1..", ALT_SETTING);
    r = libusb_set_interface_alt_setting(aHandle, 1, ALT_SETTING); 
    if (r < 0) {
        fprintf(stderr, "Error setting alternative setting %u for interface 1: %s\n", ALT_SETTING, libusb_error_name(r));
        libusb_close(aHandle);
        return r;
    }
#endif

    return 0;
}
Пример #6
0
int prog_console(char* logfile) {
	
	if(libusb_set_configuration(device, 1) < 0) {
		
		printf("[Program] Error setting configuration.\r\n");
		return -1;
		
	}
	
	if(libusb_claim_interface(device, 1) < 0) {
		
		printf("[Program] Error claiming interface.\r\n");
		return -1;
		
	}
	
	if(libusb_set_interface_alt_setting(device, 1, 1) < 0) {
		
		printf("[Program] Error claiming alt interface.\r\n");
		return -1;
		
	}
	
	char* buffer = malloc(BUF_SIZE);
	if(buffer == NULL) {
		
		printf("[Program] Error allocating memory.\r\n");
		return -1;
		
	}
	
	FILE* fd = NULL;
	if(logfile != NULL) {
		
	    fd = fopen(logfile, "w");
	    if(fd == NULL) {
	        printf("[Program] Unable to open log file.\r\n");
	        free(buffer);
	        return -1;
	    }
		
	}
	
	printf("[Program] Attached to Recovery Console.\r\n");
	
	if (logfile)
		printf("[Program] Output being logged to: %s.\r\n", logfile);
	
	read_history(CMD_LOG);
	
	while(1) {
		
		int bytes = 0;
		
		memset(buffer, 0, BUF_SIZE);
		libusb_bulk_transfer(device, 0x81, buffer, BUF_SIZE, &bytes, 500);
		
		if (bytes>0) {
			int i;
            
			for(i = 0; i < bytes; ++i) {
				
				fprintf(stdout, "%c", buffer[i]);
				if(fd) fprintf(fd, "%c", buffer[i]);
				
			}
		}
		
		char *command = readline("iRecovery> ");
		
		if (command != NULL && *command) {
			
			
			add_history(command);
			write_history(CMD_LOG);
			
			if(fd) fprintf(fd, ">%s\n", command);
			
			if (command[0] == '/' && strlen(command) > 1 && command[1] != ' ' && prog_parse(&command[1]) < 0) {
				
				free(command);
				continue;
			}
			
			device_sendcmd(&command);
			
			char* action = strtok(strdup(command), " ");
			
			if (! strcmp(action, "getenv")) {
				char response[0x200];
				libusb_control_transfer(device, 0xC0, 0, 0, 0, response, 0x200, 1000);
				printf("Env: %s\r\n", response);
				
			}
			
			if (! strcmp(action, "reboot"))
				return -1;
			
		}
		
		free(command);
	}
	
	
	free(buffer);
	if(fd) fclose(fd);
	libusb_release_interface(device, 1);
}
Пример #7
0
static int lusb_change_setting(void *driver, uint8_t setting)
{
    struct bladerf_lusb *lusb = (struct bladerf_lusb *) driver;
    int status = libusb_set_interface_alt_setting(lusb->handle, 0, setting);
    return error_conv(status);
}
Пример #8
0
transport_t::transport_t(const usb_context_ptr_t &ctx_, const device_ptr_t &dev,
                         const notifier_t *terminator) :
        ctx_(ctx_), dev_(dev), terminator_(terminator), claimed_interface_(false),
        writer_termination_requested_(false), cur_consumed_(), read_window_size_()
{
    stream_buffer_.resize(stream_buffer_size_);

    std::shared_ptr<libusb_device> dev_info(libusb_get_device(dev_.get()),
        [](libusb_device* d){libusb_unref_device(d);});
    assert(dev_info);

    TA_TRACE() << "Retrieving USB configuration";
    libusb_config_descriptor *config = 0;
    //We're always using the first configuration
    if (libusb_get_config_descriptor(dev_info.get(), 0, &config) != 0)
        throw std::runtime_error("Failed to get USB configuration");
    ON_BLOCK_EXIT([=]{libusb_free_config_descriptor(config);});

    uint8_t interface_id=0, endpoint_in=0, endpoint_out=0;
    bool endpoint_in_found = false, endpoint_out_found = false;
    int alt_setting_id=-1;

    for(interface_id=0; interface_id<config->bNumInterfaces; ++interface_id) {
        const libusb_interface *inter = &config->interface[interface_id];
        for(int n=0; n<inter->num_altsetting; ++n) {
            endpoint_in_found = false;
            endpoint_out_found = false;

            const libusb_interface_descriptor *interdesc = &inter->altsetting[n];
            alt_setting_id = interdesc->bAlternateSetting;
            for(int k=0; k<(int)interdesc->bNumEndpoints; k++) {
                const libusb_endpoint_descriptor *epdesc = &interdesc->endpoint[k];
                if ((epdesc->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) != LIBUSB_TRANSFER_TYPE_BULK)
                    continue;

                int dir = epdesc->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK;
                if (dir == LIBUSB_ENDPOINT_IN) {
                    endpoint_in = epdesc->bEndpointAddress;
                    endpoint_in_found = true;
                    //The read buffer size must be a multiply of wMaxPacketSize
                    //to avoid buffer overruns.
                    read_window_size_ = (stream_buffer_size_ - AA_PACKET_HEADER_SIZE);
                    read_window_size_ -= (read_window_size_ % epdesc->wMaxPacketSize);
                } else {
                    endpoint_out = epdesc->bEndpointAddress;
                    endpoint_out_found = true;
                }
            }

            if (endpoint_in_found && endpoint_out_found)
                break;
        }

        if (endpoint_in_found && endpoint_out_found)
            break;
    }

    if (!endpoint_out || !endpoint_in)
        throw std::runtime_error("Failed to find bulk in/out endpoints on the ACC device");

    TA_DEBUG() << "Found bulk endpoints: "<< (int)endpoint_in << " and " << (int)endpoint_out
        << ", config " << alt_setting_id << ", interface " << (int)interface_id;

    int ret = -1;
    for(int n = 0; n<10; ++n) {
        ret = libusb_claim_interface(dev.get(), interface_id);
        if (ret == 0)
            break;
        TA_DEBUG() << "Failed to claim USB interface, try " << n;
        terminator_->sleep(200);
    }
    if (ret != 0) {
        str_out_t p;
        p << "Failed to claim USB interface: " << libusb_error_name(ret);
        throw std::runtime_error(p);
    }

    TA_DEBUG() << "Claimed USB interface";

    ret = libusb_set_interface_alt_setting(dev.get(), interface_id, alt_setting_id);
    if (ret != 0) {
        str_out_t p;
        p << "Failed to select configuration " << alt_setting_id;
        throw std::runtime_error(p);
    }

    TA_INFO() << "USB interface ready";

    assert(read_window_size_);

    this->claimed_interface_ = true;
    this->endpoint_in_ = endpoint_in;
    this->endpoint_out_ = endpoint_out;
    this->interface_id_ = interface_id;

    this->writer_thread_ = std::thread([](transport_t *t){t->writer_loop();}, this);
}
Пример #9
0
int main(int argc, char **argv) {
    const char *mode = "CGRAY";
    int resolution = 100;
    if(argc > 1) {
        switch(*argv[1]) {
            case 'c': mode = "CGRAY";  break;
            case 'g': mode = "GRAY64"; break;
            case 't': mode = "TEXT";   break;
            case '-': mode = NULL;     break;
            default:
                fprintf(stderr, "ERROR: unrecognised mode, "
                                "should be one of [cgt]\n");
                return 1;
        }
    }
    if(argc > 2) {
        resolution = atoi(argv[2]);
        if(resolution < 100 || resolution > 600 || resolution % 100) {
            fprintf(stderr, "ERROR: resolution must be a positive "
                            "multiple of 100 no greater than 600\n");
            return 1;
        }
    }

    libusb_context *context;
    libusb_init(&context);
    device_handle = libusb_open_device_with_vid_pid(context, VID, PID);
    if(!device_handle) {
        fprintf(stderr, "ERROR: Unable to find device "
                        "(Vendor ID = %04x, Product ID = %04x)\n",
                VID, PID);
        return 1;
    }
    libusb_claim_interface(device_handle, 0);
    libusb_set_interface_alt_setting(device_handle, 0, 0);

    control_in_vendor_device(1, 2, 0, 255); /* returns 05 10 01 02 00 */
    if(mode) {
        char *config = build_config(
                mode, MIN(resolution, 300), resolution,
                PAGE_WIDTH * MIN(resolution, 300)/100,
                PAGE_HEIGHT * resolution/100);
        send_config(config); free(config);
    }
    int page = 1;
    FILE *fp = NULL;
    int sleep_time = 0;
    while(1) {
        unsigned char buf[0x1000];
        int num_bytes = bulk_read(4, buf, 0x1000);
        if(num_bytes) sleep_time = 0;
        if(num_bytes > 2) {
            if(!fp) {
                char fname[8];
                snprintf(fname, 8, "%03d.raw", page);
                fprintf(stderr, "Opening '%s'...\n", fname);
                fp = fopen(fname, "wb");
            }
            fwrite(buf, 1, num_bytes, fp);
        } else if(num_bytes == 0 && sleep_time < 10) {
#ifdef DEBUG
            fprintf(stderr, "Sleeping\n");
#endif
            sleep_time++;
            usleep(200 * 1000);
        } else if(num_bytes == 2 && buf[0] == 0xc2 && buf[1] == 0x00) {
            fprintf(stderr, "ERROR: Nothing to scan\n"); break;
        } else if(num_bytes == 2 && buf[0] == 0xc3 && buf[1] == 0x00) {
            fprintf(stderr, "ERROR: Paper jam\n"); break;
        } else if(num_bytes == 1 && buf[0] == 0x80) {
            fprintf(stderr, "No more pages\n"); break;
        } else if((num_bytes == 1 && buf[0] == 0x81) || sleep_time >= 10) {
            fprintf(stderr, "Feeding in another page");
            if(sleep_time >= 10) fprintf(stderr, " (timeout)");
            fprintf(stderr, "\n");
            fclose(fp); fp = NULL;
            send_config("");
            page++;
            sleep_time = 0;
        } else if(num_bytes == 1 && buf[0] == 0xc3) {
            fprintf(stderr, "Paper jam\n"); break;
        } else if(num_bytes == 1 && buf[0] == 0xc4) {
            fprintf(stderr, "Scan aborted\n"); break;
        } else {
            fprintf(stderr, "Received unknown data: %02x", buf[0]);
            if(num_bytes == 2) fprintf(stderr, " %02x", buf[1]);
            fprintf(stderr, "\n");
            break;
        }
    }
    if(fp) fclose(fp);
    control_in_vendor_device(2, 2, 0, 255); /* returns 05 10 02 02 00 */

    libusb_release_interface(device_handle, 0);
    libusb_close(device_handle);
    libusb_exit(context);
    return 0;
}
Пример #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_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;
}
Пример #11
0
int main(int argc, char **argv) {

	FILE *pFile = NULL;

	int size;
	long lSize;

	unsigned char *buffer;
	unsigned char *buf2 = calloc(300, sizeof(unsigned char));

	if (argc < 2) {
		fprintf(stderr, "Missing upload filename \n\n");
		fprintf(stderr, "Usage: \n");
		fprintf(stderr, "ISP808 <uploadfile> \n");
		exit(1);;
	}
	pFile = fopen(argv[1], "rb");

	if (pFile == NULL) {
		fprintf(stderr, "ERROR: Unable to open file %s \n", argv[1]);
		exit(1);
	}

	// obtain file size:
	fseek(pFile, 0, SEEK_END);
	lSize = ftell(pFile);
	rewind(pFile);



	// allocate memory to contain the whole file:
	buffer = calloc(lSize, sizeof(unsigned char));

	if (buffer == NULL) {
		fputs("Memory error", stderr);
		exit(2);
	}

	size = fread(buffer, 1, lSize, pFile);
	if (size != lSize) {
		fputs("Reading error", stderr);
		exit(3);
	}

	libusb_context *context;
	libusb_init(&context);

	libusb_set_debug(context, 3);

	device_handle = libusb_open_device_with_vid_pid(context, VID, PID);
	if (!device_handle) {
		fprintf(stderr, "ERROR: Unable to find device "
			"(Vendor ID = %04x, Product ID = %04x)\n", VID, PID);
		fprintf(stderr, "Press the Mode Button and connect the cam to USB \n");

		return 1;
	}
	libusb_claim_interface(device_handle, 2);

	libusb_set_interface_alt_setting(device_handle, 0, 0);

	usleep(100);

	// Get the installed version

	fprintf(stdout, "\nRead 808 Version \n");
	GetVersion();
	GetVersion1();
	GetVersion2();

	fprintf(stdout, "\nStart Uploading the file: %s \n",argv[1]);

	char defout[] = { 0x00, 0x80, 0x04, 0x00, 0x2d, 0x10, 0x00, 0x00 };

	control_in_vendor_device(0x70, 0, 0, 5);

	usleep(100);

	control_out(0xfd, 0, 0x4f3, defout, 8);

	usleep(200); // Fix me

	// Download the code

	fprintf(stdout, "\nDownload Code.... \n");

	bulk_write(3, buffer, lSize);
	usleep(200);

	char defout2[] = { 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
			0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 };

	control_out(0xfd, 0, 0x4f1, defout2, 0x10);

	usleep(100);

	// Dont know why
	bulk_write(3, buf2, 256);

	fprintf(stdout, "\nDownload Ready.... \n");
	usleep(100);

	if (pFile)
		fclose(pFile);

	free(buffer);

	libusb_release_interface(device_handle, 0);
	libusb_close(device_handle);
	libusb_exit(context);
	return 0;
}
Пример #12
0
/* ----
 * device_open()
 *
 *	Open a specific Open8055 by board number.
 * ----
 */
static PyObject *
device_open(PyObject *self, PyObject *args)
{
	int						cardNumber;
	Open8055Card		   *card;
	libusb_device_handle   *dev;
	int						rc;
	int						interface = 0;
	char					errbuf[1024];

	/* ----
	 * Parse command arguments
	 * ----
	 */
	if (!PyArg_ParseTuple(args, "i", &cardNumber))
		return NULL;
	if (cardNumber < 0 || cardNumber >= OPEN8055_MAX_CARDS)
	{
		PyErr_SetString(PyExc_ValueError, "invalid card number");
		return NULL;
	}

	/* ----
	 * Sanity checks
	 * ----
	 */
	if (deviceCard[cardNumber].handle != NULL)
	{
		PyErr_SetString(PyExc_RuntimeError, "card already open");
		return NULL;
	}

	if (device_present(self, args) == NULL)
		return NULL;

	/* ----
	 * Allocate the libusb asynchronous transfer structures.
	 * ----
	 */
	card = &deviceCard[cardNumber];
	if ((card->readTransfer = libusb_alloc_transfer(0)) == NULL)
	{
		PyErr_SetString(PyExc_RuntimeError, "libusb_alloc_transfer() failed");
		return NULL;
	}
	if ((card->writeTransfer = libusb_alloc_transfer(0)) == NULL)
	{
		PyErr_SetString(PyExc_RuntimeError, "libusb_alloc_transfer() failed");
		libusb_free_transfer(card->readTransfer);
		return NULL;
	}

	/* ----
	 * Open the device.
	 * ----
	 */
	dev = libusb_open_device_with_vid_pid(
			libusbCxt, OPEN8055_VID, OPEN8055_PID + cardNumber);
	if (dev == NULL)
	{
		PyErr_SetString(PyExc_RuntimeError,
				"libusb_open_device_with_vid_pid() failed");
		libusb_free_transfer(card->readTransfer);
		libusb_free_transfer(card->writeTransfer);
		return NULL;
	}

	/* ----
	 * If a kernel driver is active, detach it.
	 * ----
	 */
	if ((rc = libusb_kernel_driver_active(dev, interface)) < 0)
	{
		snprintf(errbuf, sizeof(errbuf),
				"libusb_kernel_driver_active() failed - %s", 
				libusb_strerror(rc));
		PyErr_SetString(PyExc_RuntimeError, errbuf);
		libusb_close(dev);
		libusb_free_transfer(card->readTransfer);
		libusb_free_transfer(card->writeTransfer);
		return NULL;
	}
	else
	{
		deviceCard[cardNumber].hadKernelDriver = rc;
		if (rc != 0)
		{
			if ((rc = libusb_detach_kernel_driver(dev, interface)) != 0)
			{
				snprintf(errbuf, sizeof(errbuf),
						"libusb_detach_kernel_driver() failed - %s", 
						libusb_strerror(rc));
				PyErr_SetString(PyExc_RuntimeError, errbuf);
				libusb_close(dev);
				libusb_free_transfer(card->readTransfer);
				libusb_free_transfer(card->writeTransfer);
				return NULL;
			}
		}
	}

	/* ----
	 * Set configuration
	 * ----
	 */
	if (libusb_set_configuration(dev, 1) != 0)
	{
		snprintf(errbuf, sizeof(errbuf),
				"libusb_set_configuration() failed - %s", 
				libusb_strerror(rc));
		PyErr_SetString(PyExc_RuntimeError, errbuf);
		if (deviceCard[cardNumber].hadKernelDriver)
			libusb_attach_kernel_driver(dev, interface);
		libusb_close(dev);
		libusb_free_transfer(card->readTransfer);
		libusb_free_transfer(card->writeTransfer);
		return NULL;
	}

	/* ----
	 * Claim the interface.
	 * ----
	 */
	if (libusb_claim_interface(dev, interface) != 0)
	{
		snprintf(errbuf, sizeof(errbuf),
				"libusb_claim_interface() failed - %s", 
				libusb_strerror(rc));
		PyErr_SetString(PyExc_RuntimeError, errbuf);
		if (deviceCard[cardNumber].hadKernelDriver)
			libusb_attach_kernel_driver(dev, interface);
		libusb_close(dev);
		libusb_free_transfer(card->readTransfer);
		libusb_free_transfer(card->writeTransfer);
		return NULL;
	}

	/* ----
	 * Activate alternate setting
	 * ----
	 */
	if (libusb_set_interface_alt_setting(dev, interface, 0) != 0)
	{
		snprintf(errbuf, sizeof(errbuf),
				"libusb_set_interface_alt_setting() failed - %s", 
				libusb_strerror(rc));
		PyErr_SetString(PyExc_RuntimeError, errbuf);
		libusb_release_interface(dev, interface);
		if (deviceCard[cardNumber].hadKernelDriver)
			libusb_attach_kernel_driver(dev, interface);
		libusb_close(dev);
		libusb_free_transfer(card->readTransfer);
		libusb_free_transfer(card->writeTransfer);
		return NULL;
	}

	deviceCard[cardNumber].handle = dev;

	return Py_BuildValue("i", cardNumber);
}
Пример #13
0
int main(int argc, char **argv)
{
	struct dfu_if _rt_dif, _dif, *dif = &_dif;
	int num_devs;
	int num_ifs;
	unsigned int transfer_size = 0;
	unsigned int host_page_size;
    enum mode mode = MODE_DOWNLOAD; //MODE_NONE;
	struct dfu_status status;
	struct usb_dfu_func_descriptor func_dfu = {0}, func_dfu_rt = {0};
	libusb_context *ctx;
	struct dfu_file file;
	char *alt_name = NULL; /* query alt name if non-NULL */
	char *device_id_filter = NULL;
	unsigned char active_alt_name[MAX_DESC_STR_LEN+1];
	char *end;
	int final_reset = 0;
	int ret;
	int dfuse = 0;
	unsigned int dfuse_address = 0; /* FIXME allow address to be zero? */

    struct libusb_device_descriptor desc;

	host_page_size = getpagesize();
	memset(dif, 0, sizeof(*dif));
    /*if ( argc < 2 )
    {
        fprintf( stderr, "unable to get file name from command line\n");
        exit( 1 );
    }
    file.name = argv[1];*/


	while (1) {
		int c, option_index = 0;
		c = getopt_long(argc, argv, "hVvled:p:c:i:a:t:U:D:Rs:", opts,
				&option_index);
		if (c == -1)
			break;

		switch (c) {
		case 'h':
			help();
			exit(0);
			break;
		case 'V':
			mode = MODE_VERSION;
			break;
		case 'v':
			verbose++;
			break;
		case 'l':
			mode = MODE_LIST;
			break;
		case 'e':
			mode = MODE_DETACH;
			break;
		case 'd':
			device_id_filter = optarg;
			break;
		case 'p':
			// Parse device path
			dif->path = optarg;
			dif->flags |= DFU_IFF_PATH;
			ret = resolve_device_path(dif);
			if (ret < 0) {
				fprintf(stderr, "unable to parse `%s'\n",
				    optarg);
				exit(2);
			}
			if (!ret) {
				fprintf(stderr, "cannot find `%s'\n", optarg);
				exit(1);
			}
			break;
		case 'c':
			// Configuration
			dif->configuration = atoi(optarg);
			dif->flags |= DFU_IFF_CONFIG;
			break;
		case 'i':
			// Interface
			dif->interface = atoi(optarg);
			dif->flags |= DFU_IFF_IFACE;
			break;
		case 'a':
			// Interface Alternate Setting
			dif->altsetting = strtoul(optarg, &end, 0);
			if (*end)
				alt_name = optarg;
			dif->flags |= DFU_IFF_ALT;
			break;
		case 't':
			transfer_size = atoi(optarg);
			break;
		case 'U':
			mode = MODE_UPLOAD;
			file.name = optarg;
			break;
		case 'D':
			mode = MODE_DOWNLOAD;
			file.name = optarg;
			break;
		case 'R':
			final_reset = 1;
			break;
		case 's':
			dfuse = 1;
			if (strcmp(optarg, "default")) {
			    dfuse_address = strtoul(optarg, &end, 0);
			    if (!dfuse_address || (*end)) {
				fprintf(stderr, "invalid dfuse address: %s\n",
					optarg);
				exit(2);
			    }
			}
			break;
		default:
			help();
			exit(2);
		}
	}

	print_version();
	if (mode == MODE_VERSION) {
		exit(0);
	}

	if (mode == MODE_NONE) {
		fprintf(stderr, "Error: You need to specify one of -D or -U\n\n");
		help();
		exit(2);
	}

	if (device_id_filter) {
		// Parse device ID
		parse_vendprod(&dif->vendor, &dif->product, device_id_filter);
		printf("Filter on vendor = 0x%04x product = 0x%04x\n",
		       dif->vendor, dif->product);
		if (dif->vendor)
			dif->flags |= DFU_IFF_VENDOR;
		if (dif->product)
			dif->flags |= DFU_IFF_PRODUCT;
	}

	ret = libusb_init(&ctx);
	if (ret) {
		fprintf(stderr, "unable to initialize libusb: %i\n", ret);
		return EXIT_FAILURE;
	}

    /*
	if (verbose > 1) {
		libusb_set_debug(ctx, 255);
	}

	if (mode == MODE_LIST) {
		list_dfu_interfaces(ctx);
		exit(0);
	}*/

	dfu_init(5000);

	num_devs = count_dfu_devices(ctx, dif);
	if (num_devs == 0) {
		fprintf(stderr, "No DFU capable USB device found\n");
		exit(1);
	} else if (num_devs > 1) {
		/* We cannot safely support more than one DFU capable device
		 * with same vendor/product ID, since during DFU we need to do
		 * a USB bus reset, after which the target device will get a
		 * new address */
		fprintf(stderr, "More than one DFU capable USB device found, "
		       "you might try `--list' and then disconnect all but one "
		       "device\n");
		exit(3);
	}
	if (!get_first_dfu_device(ctx, dif))
		exit(3);

	/* We have exactly one device. Its libusb_device is now in dif->dev */

	printf("Opening DFU capable USB device... ");
	ret = libusb_open(dif->dev, &dif->dev_handle);
	if (ret || !dif->dev_handle) {
		fprintf(stderr, "Cannot open device\n");
		exit(1);
	}

	/* try to find first DFU interface of device */
	memcpy(&_rt_dif, dif, sizeof(_rt_dif));
	if (!get_first_dfu_if(&_rt_dif))
		exit(1);

	printf("ID %04x:%04x\n", _rt_dif.vendor, _rt_dif.product);

	/* find set of quirks for this device */
	set_quirks(_rt_dif.vendor, _rt_dif.product);

	/* Obtain run-time DFU functional descriptor without asking device
	 * E.g. Freerunner does not like to be requested at this point */
	ret = get_cached_extra_descriptor(_rt_dif.dev, _rt_dif.configuration,
					  _rt_dif.interface, USB_DT_DFU, 0,
					  (unsigned char *) &func_dfu_rt,
					  sizeof(func_dfu_rt));
	if (ret == 7) {
		/* DFU 1.0 does not have this field */
		printf("Deducing device DFU version from functional descriptor "
		       "length\n");
		func_dfu_rt.bcdDFUVersion = libusb_cpu_to_le16(0x0100);
	} else if (ret < 9) {
		fprintf(stderr, "WARNING: Can not find cached DFU functional "
			"descriptor\n");
		printf("Warning: Assuming DFU version 1.0\n");
		func_dfu_rt.bcdDFUVersion = libusb_cpu_to_le16(0x0100);
	}
	printf("Run-time device DFU version %04x\n",
	       libusb_le16_to_cpu(func_dfu_rt.bcdDFUVersion));

	/* Transition from run-Time mode to DFU mode */
	if (!(_rt_dif.flags & DFU_IFF_DFU)) {
		/* In the 'first round' during runtime mode, there can only be one
		* DFU Interface descriptor according to the DFU Spec. */

		/* FIXME: check if the selected device really has only one */

		printf("Claiming USB DFU Runtime Interface...\n");
		if (libusb_claim_interface(_rt_dif.dev_handle, _rt_dif.interface) < 0) {
			fprintf(stderr, "Cannot claim interface %d\n",
				_rt_dif.interface);
			exit(1);
		}

		if (libusb_set_interface_alt_setting(_rt_dif.dev_handle, _rt_dif.interface, 0) < 0) {
			fprintf(stderr, "Cannot set alt interface zero\n");
			exit(1);
		}

		printf("Determining device status: ");
		if (dfu_get_status(_rt_dif.dev_handle, _rt_dif.interface, &status ) < 0) {
			fprintf(stderr, "error get_status\n");
			exit(1);
		}
		printf("state = %s, status = %d\n", 
		       dfu_state_to_string(status.bState), status.bStatus);
		if (!(quirks & QUIRK_POLLTIMEOUT))
			usleep(status.bwPollTimeout * 1000);

		switch (status.bState) {
		case DFU_STATE_appIDLE:
		case DFU_STATE_appDETACH:
			printf("Device really in Runtime Mode, send DFU "
			       "detach request...\n");
			if (dfu_detach(_rt_dif.dev_handle, 
				       _rt_dif.interface, 1000) < 0) {
				fprintf(stderr, "error detaching\n");
				exit(1);
				break;
			}
			libusb_release_interface(_rt_dif.dev_handle,
						 _rt_dif.interface);
			if (func_dfu_rt.bmAttributes & USB_DFU_WILL_DETACH) {
				printf("Device will detach and reattach...\n");
			} else {
				printf("Resetting USB...\n");
				ret = libusb_reset_device(_rt_dif.dev_handle);
				if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND)
					fprintf(stderr, "error resetting "
						"after detach\n");
			}
			sleep(2);
			break;
		case DFU_STATE_dfuERROR:
			printf("dfuERROR, clearing status\n");
			if (dfu_clear_status(_rt_dif.dev_handle,
					     _rt_dif.interface) < 0) {
				fprintf(stderr, "error clear_status\n");
				exit(1);
				break;
			}
			break;
		default:
			fprintf(stderr, "WARNING: Runtime device already "
				"in DFU state ?!?\n");
			goto dfustate;
			break;
		}
		libusb_release_interface(_rt_dif.dev_handle,
					 _rt_dif.interface);
		libusb_close(_rt_dif.dev_handle);

		if (mode == MODE_DETACH) {
			libusb_exit(ctx);
			exit(0);
		}

		/* now we need to re-scan the bus and locate our device */
//		if (usb_find_devices() < 2)
//			printf("not at least 2 device changes found ?!?\n");

		if (dif->flags & DFU_IFF_PATH) {
			ret = resolve_device_path(dif);
			if (ret < 0) {
				fprintf(stderr,
				    "internal error: cannot re-parse `%s'\n",
				    dif->path);
				abort();
			}
			if (!ret) {
				fprintf(stderr,
				    "Cannot resolve path after RESET?\n");
				exit(1);
			}
		}

		num_devs = count_dfu_devices(ctx, dif);
		if (num_devs == 0) {
			fprintf(stderr, "Lost device after RESET?\n");
			exit(1);
		} else if (num_devs > 1) {
			fprintf(stderr, "More than one DFU capable USB "
				"device found, you might try `--list' and "
				"then disconnect all but one device\n");
			exit(1);
		}
		if (!get_first_dfu_device(ctx, dif))
			exit(3);

		printf("Opening DFU USB Device...\n");
		ret = libusb_open(dif->dev, &dif->dev_handle);
		if (ret || !dif->dev_handle) {
			fprintf(stderr, "Cannot open device\n");
			exit(1);
		}
	} else {
		/* we're already in DFU mode, so we can skip the detach/reset
		 * procedure */
	}

dfustate:
	if (alt_name) {
		int n;

		n = find_dfu_if(dif->dev, &alt_by_name, alt_name);
		if (!n) {
			fprintf(stderr, "No such Alternate Setting: \"%s\"\n",
			    alt_name);
			exit(1);
		}
		if (n < 0) {
			fprintf(stderr, "Error %d in name lookup\n", n);
			exit(1);
		}
		dif->altsetting = n-1;
	}

	num_ifs = count_matching_dfu_if(dif);
	if (num_ifs < 0) {
		fprintf(stderr, "No matching DFU Interface after RESET?!?\n");
		exit(1);
	} else if (num_ifs > 1 ) {
		printf("Detected interfaces after DFU transition\n");
		list_dfu_interfaces(ctx);
		fprintf(stderr, "We have %u DFU Interfaces/Altsettings,"
			" you have to specify one via --intf / --alt"
			" options\n", num_ifs);
		exit(1);
	}

	if (!get_matching_dfu_if(dif)) {
		fprintf(stderr, "Can't find the matching DFU interface/"
			"altsetting\n");
		exit(1);
	}
	print_dfu_if(dif, NULL);
	if (get_alt_name(dif, active_alt_name) > 0)
		dif->alt_name = active_alt_name;
	else
		dif->alt_name = NULL;

#if 0
	printf("Setting Configuration %u...\n", dif->configuration);
	if (libusb_set_configuration(dif->dev_handle, dif->configuration) < 0) {
		fprintf(stderr, "Cannot set configuration\n");
		exit(1);
	}
#endif
	printf("Claiming USB DFU Interface...\n");
	if (libusb_claim_interface(dif->dev_handle, dif->interface) < 0) {
		fprintf(stderr, "Cannot claim interface\n");
		exit(1);
	}

	printf("Setting Alternate Setting #%d ...\n", dif->altsetting);
	if (libusb_set_interface_alt_setting(dif->dev_handle, dif->interface, dif->altsetting) < 0) {
		fprintf(stderr, "Cannot set alternate interface\n");
		exit(1);
	}

status_again:
	printf("Determining device status: ");
	if (dfu_get_status(dif->dev_handle, dif->interface, &status ) < 0) {
		fprintf(stderr, "error get_status\n");
		exit(1);
	}
	printf("state = %s, status = %d\n",
	       dfu_state_to_string(status.bState), status.bStatus);
	if (!(quirks & QUIRK_POLLTIMEOUT))
		usleep(status.bwPollTimeout * 1000);

	switch (status.bState) {
	case DFU_STATE_appIDLE:
	case DFU_STATE_appDETACH:
		fprintf(stderr, "Device still in Runtime Mode!\n");
		exit(1);
		break;
	case DFU_STATE_dfuERROR:
		printf("dfuERROR, clearing status\n");
		if (dfu_clear_status(dif->dev_handle, dif->interface) < 0) {
			fprintf(stderr, "error clear_status\n");
			exit(1);
		}
		goto status_again;
		break;
	case DFU_STATE_dfuDNLOAD_IDLE:
	case DFU_STATE_dfuUPLOAD_IDLE:
		printf("aborting previous incomplete transfer\n");
		if (dfu_abort(dif->dev_handle, dif->interface) < 0) {
			fprintf(stderr, "can't send DFU_ABORT\n");
			exit(1);
		}
		goto status_again;
		break;
	case DFU_STATE_dfuIDLE:
		printf("dfuIDLE, continuing\n");
		break;
	}

	if (DFU_STATUS_OK != status.bStatus ) {
		printf("WARNING: DFU Status: '%s'\n",
			dfu_status_to_string(status.bStatus));
		/* Clear our status & try again. */
		dfu_clear_status(dif->dev_handle, dif->interface);
		dfu_get_status(dif->dev_handle, dif->interface, &status);

		if (DFU_STATUS_OK != status.bStatus) {
			fprintf(stderr, "Error: %d\n", status.bStatus);
			exit(1);
		}
		if (!(quirks & QUIRK_POLLTIMEOUT))
			usleep(status.bwPollTimeout * 1000);
	}

	/* Get the DFU mode DFU functional descriptor
	 * If it is not found cached, we will request it from the device */
	ret = get_cached_extra_descriptor(dif->dev, dif->configuration,
					  dif->interface, USB_DT_DFU, 0,
					  (unsigned char *) &func_dfu,
					  sizeof(func_dfu));
	if (ret < 7) {
		fprintf(stderr, "Error obtaining cached DFU functional "
			"descriptor\n");
		ret = usb_get_any_descriptor(dif->dev_handle,
					     USB_DT_DFU, 0,
					     (unsigned char *) &func_dfu,
					     sizeof(func_dfu));
	}
	if (ret == 7) {
		printf("Deducing device DFU version from functional descriptor "
		       "length\n");
		func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100);
	} else if (ret < 9) {
		printf("Error obtaining DFU functional descriptor\n");
		printf("Warning: Assuming DFU version 1.0\n");
		func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100);
		printf("Warning: Transfer size can not be detected\n");
		func_dfu.wTransferSize = 0;
	}
	printf("DFU mode device DFU version %04x\n",
	       libusb_le16_to_cpu(func_dfu.bcdDFUVersion));

	if (func_dfu.bcdDFUVersion == 0x11a)
		dfuse = 1;

	if (!transfer_size) {
		transfer_size = libusb_le16_to_cpu(func_dfu.wTransferSize);
		printf("Device returned transfer size %i\n", transfer_size);
	}

	/* if returned zero or not detected (and not user specified) */
	if (!transfer_size) {
		transfer_size = DEFAULT_TRANSFER_SIZE;
		printf("Warning: Trying default transfer size %i\n",
			transfer_size);
	}
	/* limitation of Linux usbdevio */
	if (transfer_size > host_page_size) {
		transfer_size = host_page_size;
		printf("Limited transfer size to %i\n", transfer_size);
	}
	/* DFU specification */
	//struct libusb_device_descriptor desc;
	if (libusb_get_device_descriptor(dif->dev, &desc)) {
		fprintf(stderr, "Error: Failed to get device descriptor\n");
		exit(1);
	}
	if (transfer_size < desc.bMaxPacketSize0) {
		transfer_size = desc.bMaxPacketSize0;
		printf("Adjusted transfer size to %i\n", transfer_size);
	}

	switch (mode) {
	case MODE_UPLOAD:
		file.fd = open(file.name, O_WRONLY|O_CREAT|O_EXCL, 0644);
		if (file.fd < 0) {
			perror(file.name);
			exit(1);
		}
		if (dfuse) {
		    if (dfuse_do_upload(dif, transfer_size, file,
					dfuse_address) < 0)
			exit(1);
		} else {
		    if (dfuload_do_upload(dif, transfer_size, file) < 0)
			exit(1);
		}
		close(file.fd);
		break;
	case MODE_DOWNLOAD:
		file.fd = open(file.name, O_RDONLY|O_BINARY);
		if (file.fd < 0) {
			perror(file.name);
			exit(1);
		}
		ret = parse_dfu_suffix(&file);
		if (ret < 0)
			exit(1);
		if (ret == 0) {
			fprintf(stderr, "Warning: File has no DFU suffix\n");
		} else if (file.bcdDFU != 0x0100 && file.bcdDFU != 0x11a) {
			fprintf(stderr, "Unsupported DFU file revision "
				"%04x\n", file.bcdDFU);
			exit(1);
		}
		if (file.idVendor != 0xffff &&
		    dif->vendor != file.idVendor) {
			fprintf(stderr, "Warning: File vendor ID %04x does "
				"not match device %04x\n", file.idVendor, dif->vendor);
		}
		if (file.idProduct != 0xffff &&
		    dif->product != file.idProduct) {
			fprintf(stderr, "Warning: File product ID %04x does "
				"not match device %04x\n", file.idProduct, dif->product);
		}
		if (dfuse || file.bcdDFU == 0x11a) {
		        if (dfuse_do_dnload(dif, transfer_size, file,
							dfuse_address) < 0)
				exit(1);
		} else {
			if (dfuload_do_dnload(dif, transfer_size, file) < 0)
				exit(1);
	 	}
		close(file.fd);
		break;
	default:
		fprintf(stderr, "Unsupported mode: %u\n", mode);
		exit(1);
	}

	if (final_reset) {
		if (dfu_detach(dif->dev_handle, dif->interface, 1000) < 0) {
			fprintf(stderr, "can't detach\n");
		}
		printf("Resetting USB to switch back to runtime mode\n");
		ret = libusb_reset_device(dif->dev_handle);
		if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND) {
			fprintf(stderr, "error resetting after download\n");
		}
	}

	libusb_close(dif->dev_handle);
	libusb_exit(ctx);
	exit(0);
}