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