struct mpsse_ctx *mpsse_open(const uint16_t *vid, const uint16_t *pid, const char *description, const char *serial, const char *location, int channel) { struct mpsse_ctx *ctx = calloc(1, sizeof(*ctx)); int err; if (!ctx) return 0; bit_copy_queue_init(&ctx->read_queue); ctx->read_chunk_size = 16384; ctx->read_size = 16384; ctx->write_size = 16384; ctx->read_chunk = malloc(ctx->read_chunk_size); ctx->read_buffer = malloc(ctx->read_size); ctx->write_buffer = malloc(ctx->write_size); if (!ctx->read_chunk || !ctx->read_buffer || !ctx->write_buffer) goto error; ctx->interface = channel; ctx->index = channel + 1; ctx->usb_read_timeout = 5000; ctx->usb_write_timeout = 5000; err = libusb_init(&ctx->usb_ctx); if (err != LIBUSB_SUCCESS) { LOG_ERROR("libusb_init() failed with %s", libusb_error_name(err)); goto error; } if (!open_matching_device(ctx, vid, pid, description, serial, location)) { /* Four hex digits plus terminating zero each */ char vidstr[5]; char pidstr[5]; LOG_ERROR("unable to open ftdi device with vid %s, pid %s, description '%s', " "serial '%s' at bus location '%s'", vid ? sprintf(vidstr, "%04x", *vid), vidstr : "*", pid ? sprintf(pidstr, "%04x", *pid), pidstr : "*", description ? description : "*", serial ? serial : "*", location ? location : "*"); ctx->usb_dev = 0; goto error; } err = libusb_control_transfer(ctx->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_SET_LATENCY_TIMER_REQUEST, 255, ctx->index, NULL, 0, ctx->usb_write_timeout); if (err < 0) { LOG_ERROR("unable to set latency timer: %s", libusb_error_name(err)); goto error; } err = libusb_control_transfer(ctx->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_SET_BITMODE_REQUEST, 0x0b | (BITMODE_MPSSE << 8), ctx->index, NULL, 0, ctx->usb_write_timeout); if (err < 0) { LOG_ERROR("unable to set MPSSE bitmode: %s", libusb_error_name(err)); goto error; } mpsse_purge(ctx); return ctx; error: mpsse_close(ctx); return 0; }
static int ftdi_quit(void) { mpsse_close(mpsse_ctx); return ERROR_OK; }