1
0
mirror of https://review.coreboot.org/flashrom.git synced 2025-04-27 15:12:36 +02:00

dediprog: port to libusb1 and use asynchronous bulk transfers for reading

This patch is based on Nico Huber's original version that was rebased
by David Hendricks for Chromium OS in
Change-Id: I84384b9d8ed53911657cf2293733531a6e11fd23

Corresponding to flashrom svn r1929.

Signed-off-by: Nico Huber <nico.huber@secunet.com>
Signed-off-by: David Hendricks <dhendrix@chromium.org>
Signed-off-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
Acked-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
This commit is contained in:
Nico Huber 2016-02-18 21:42:49 +00:00 committed by Stefan Tauner
parent c05900f3dc
commit d99a2bd049
4 changed files with 204 additions and 95 deletions

View File

@ -742,7 +742,7 @@ endif
ifeq ($(CONFIG_DEDIPROG), yes) ifeq ($(CONFIG_DEDIPROG), yes)
FEATURE_CFLAGS += -D'CONFIG_DEDIPROG=1' FEATURE_CFLAGS += -D'CONFIG_DEDIPROG=1'
PROGRAMMER_OBJS += dediprog.o PROGRAMMER_OBJS += dediprog.o
NEED_LIBUSB0 += CONFIG_DEDIPROG NEED_LIBUSB1 += CONFIG_DEDIPROG
endif endif
ifeq ($(CONFIG_SATAMV), yes) ifeq ($(CONFIG_SATAMV), yes)

View File

@ -26,25 +26,28 @@
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#include <errno.h> #include <errno.h>
#include <libusb.h>
#if IS_WINDOWS
#include <lusb0_usb.h>
#else
#include <usb.h>
#endif
#include "flash.h" #include "flash.h"
#include "chipdrivers.h" #include "chipdrivers.h"
#include "programmer.h" #include "programmer.h"
#include "spi.h" #include "spi.h"
/* LIBUSB_CALL ensures the right calling conventions on libusb callbacks.
* However, the macro is not defined everywhere. m(
*/
#ifndef LIBUSB_CALL
#define LIBUSB_CALL
#endif
#define FIRMWARE_VERSION(x,y,z) ((x << 16) | (y << 8) | z) #define FIRMWARE_VERSION(x,y,z) ((x << 16) | (y << 8) | z)
#define DEFAULT_TIMEOUT 3000 #define DEFAULT_TIMEOUT 3000
#define REQTYPE_OTHER_OUT (USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER) /* 0x43 */ #define DEDIPROG_ASYNC_TRANSFERS 8 /* at most 8 asynchronous transfers */
#define REQTYPE_OTHER_IN (USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER) /* 0xC3 */ #define REQTYPE_OTHER_OUT (LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_OTHER) /* 0x43 */
#define REQTYPE_EP_OUT (USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) /* 0x42 */ #define REQTYPE_OTHER_IN (LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_OTHER) /* 0xC3 */
#define REQTYPE_EP_IN (USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) /* 0xC2 */ #define REQTYPE_EP_OUT (LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_ENDPOINT) /* 0x42 */
static usb_dev_handle *dediprog_handle; #define REQTYPE_EP_IN (LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_ENDPOINT) /* 0xC2 */
struct libusb_context *usb_ctx;
static libusb_device_handle *dediprog_handle;
static int dediprog_in_endpoint; static int dediprog_in_endpoint;
static int dediprog_out_endpoint; static int dediprog_out_endpoint;
@ -144,6 +147,22 @@ enum dediprog_standalone_mode {
static int dediprog_firmwareversion = FIRMWARE_VERSION(0, 0, 0); static int dediprog_firmwareversion = FIRMWARE_VERSION(0, 0, 0);
enum dediprog_devtype dediprog_devicetype = DEV_UNKNOWN; enum dediprog_devtype dediprog_devicetype = DEV_UNKNOWN;
#if defined(LIBUSB_MAJOR) && defined(LIBUSB_MINOR) && defined(LIBUSB_MICRO) && \
LIBUSB_MAJOR <= 1 && LIBUSB_MINOR == 0 && LIBUSB_MICRO < 9
/* Quick and dirty replacement for missing libusb_error_name in libusb < 1.0.9 */
const char * LIBUSB_CALL libusb_error_name(int error_code)
{
if (error_code >= INT16_MIN && error_code <= INT16_MAX) {
/* 18 chars for text, rest for number (16 b should be enough), sign, nullbyte. */
static char my_libusb_error[18 + 5 + 2];
sprintf(my_libusb_error, "libusb error code %i", error_code);
return my_libusb_error;
} else {
return "UNKNOWN";
}
}
#endif
/* Returns true if firmware (and thus hardware) supports the "new" protocol */ /* Returns true if firmware (and thus hardware) supports the "new" protocol */
static bool is_new_prot(void) static bool is_new_prot(void)
{ {
@ -157,35 +176,93 @@ static bool is_new_prot(void)
} }
} }
struct dediprog_transfer_status {
int error; /* OK if 0, ERROR else */
unsigned int queued_idx;
unsigned int finished_idx;
};
static void LIBUSB_CALL dediprog_bulk_read_cb(struct libusb_transfer *const transfer)
{
struct dediprog_transfer_status *const status = (struct dediprog_transfer_status *)transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
status->error = 1;
msg_perr("SPI bulk read failed!\n");
}
++status->finished_idx;
}
static int dediprog_bulk_read_poll(const struct dediprog_transfer_status *const status, const int finish)
{
if (status->finished_idx >= status->queued_idx)
return 0;
do {
struct timeval timeout = { 10, 0 };
const int ret = libusb_handle_events_timeout(usb_ctx, &timeout);
if (ret < 0) {
msg_perr("Polling read events failed: %i %s!\n", ret, libusb_error_name(ret));
return 1;
}
} while (finish && (status->finished_idx < status->queued_idx));
return 0;
}
static int dediprog_read(enum dediprog_cmds cmd, unsigned int value, unsigned int idx, uint8_t *bytes, size_t size) static int dediprog_read(enum dediprog_cmds cmd, unsigned int value, unsigned int idx, uint8_t *bytes, size_t size)
{ {
return usb_control_msg(dediprog_handle, REQTYPE_EP_IN, cmd, value, idx, return libusb_control_transfer(dediprog_handle, REQTYPE_EP_IN, cmd, value, idx,
(char *)bytes, size, DEFAULT_TIMEOUT); (unsigned char *)bytes, size, DEFAULT_TIMEOUT);
} }
static int dediprog_write(enum dediprog_cmds cmd, unsigned int value, unsigned int idx, const uint8_t *bytes, size_t size) static int dediprog_write(enum dediprog_cmds cmd, unsigned int value, unsigned int idx, const uint8_t *bytes, size_t size)
{ {
return usb_control_msg(dediprog_handle, REQTYPE_EP_OUT, cmd, value, idx, return libusb_control_transfer(dediprog_handle, REQTYPE_EP_OUT, cmd, value, idx,
(char *)bytes, size, DEFAULT_TIMEOUT); (unsigned char *)bytes, size, DEFAULT_TIMEOUT);
} }
/* Might be useful for other USB devices as well. static for now. */
/* device parameter allows user to specify one device of multiple installed */ /* Might be useful for other USB devices as well. static for now.
static struct usb_device *get_device_by_vid_pid(uint16_t vid, uint16_t pid, unsigned int device) * num parameter allows user to specify one device of multiple installed */
static struct libusb_device_handle *get_device_by_vid_pid_number(uint16_t vid, uint16_t pid, unsigned int num)
{ {
struct usb_bus *bus; struct libusb_device **list;
struct usb_device *dev; ssize_t count = libusb_get_device_list(usb_ctx, &list);
if (count < 0) {
msg_perr("Getting the USB device list failed (%s)!\n", libusb_error_name(count));
return NULL;
}
for (bus = usb_get_busses(); bus; bus = bus->next) struct libusb_device_handle *handle = NULL;
for (dev = bus->devices; dev; dev = dev->next) ssize_t i = 0;
if ((dev->descriptor.idVendor == vid) && for (i = 0; i < count; i++) {
(dev->descriptor.idProduct == pid)) { struct libusb_device *dev = list[i];
if (device == 0) struct libusb_device_descriptor desc;
return dev; int err = libusb_get_device_descriptor(dev, &desc);
device--; if (err != 0) {
msg_perr("Reading the USB device descriptor failed (%s)!\n", libusb_error_name(err));
libusb_free_device_list(list, 1);
return NULL;
}
if ((desc.idVendor == vid) && (desc.idProduct == pid)) {
msg_pdbg("Found USB device %04"PRIx16":%04"PRIx16" at address %d-%d.\n",
desc.idVendor, desc.idProduct,
libusb_get_bus_number(dev), libusb_get_device_address(dev));
if (num == 0) {
err = libusb_open(dev, &handle);
if (err != 0) {
msg_perr("Opening the USB device failed (%s)!\n",
libusb_error_name(err));
libusb_free_device_list(list, 1);
return NULL;
}
break;
} }
num--;
}
}
libusb_free_device_list(list, 1);
return NULL; return handle;
} }
/* This function sets the GPIOs connected to the LEDs as well as IO1-IO4. */ /* This function sets the GPIOs connected to the LEDs as well as IO1-IO4. */
@ -219,7 +296,7 @@ static int dediprog_set_leds(int leds)
} }
if (ret != 0x0) { if (ret != 0x0) {
msg_perr("Command Set LED 0x%x failed (%s)!\n", leds, usb_strerror()); msg_perr("Command Set LED 0x%x failed (%s)!\n", leds, libusb_error_name(ret));
return 1; return 1;
} }
@ -332,10 +409,16 @@ static void fill_rw_cmd_payload(uint8_t *data_packet, unsigned int count, uint8_
*/ */
static int dediprog_spi_bulk_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len) static int dediprog_spi_bulk_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
{ {
int err = 1;
/* chunksize must be 512, other sizes will NOT work at all. */ /* chunksize must be 512, other sizes will NOT work at all. */
const unsigned int chunksize = 512; const unsigned int chunksize = 512;
const unsigned int count = len / chunksize; const unsigned int count = len / chunksize;
struct dediprog_transfer_status status = { 0, 0, 0 };
struct libusb_transfer *transfers[DEDIPROG_ASYNC_TRANSFERS] = { NULL, };
struct libusb_transfer *transfer;
if ((start % chunksize) || (len % chunksize)) { if ((start % chunksize) || (len % chunksize)) {
msg_perr("%s: Unaligned start=%i, len=%i! Please report a bug at flashrom@flashrom.org\n", msg_perr("%s: Unaligned start=%i, len=%i! Please report a bug at flashrom@flashrom.org\n",
__func__, start, len); __func__, start, len);
@ -352,23 +435,59 @@ static int dediprog_spi_bulk_read(struct flashctx *flash, uint8_t *buf, unsigned
int ret = dediprog_write(CMD_READ, value, idx, data_packet, sizeof(data_packet)); int ret = dediprog_write(CMD_READ, value, idx, data_packet, sizeof(data_packet));
if (ret != sizeof(data_packet)) { if (ret != sizeof(data_packet)) {
msg_perr("Command Read SPI Bulk failed, %i %s!\n", ret, usb_strerror()); msg_perr("Command Read SPI Bulk failed, %i %s!\n", ret, libusb_error_name(ret));
return 1; return 1;
} }
unsigned int i; /*
for (i = 0; i < count; i++) { * Ring buffer of bulk transfers.
ret = usb_bulk_read(dediprog_handle, 0x80 | dediprog_in_endpoint, * Poll until at least one transfer is ready,
(char *)buf + i * chunksize, chunksize, * schedule next transfers until buffer is full.
DEFAULT_TIMEOUT); */
if (ret != chunksize) {
msg_perr("SPI bulk read %i failed, expected %i, got %i %s!\n",
i, chunksize, ret, usb_strerror());
return 1;
}
}
return 0; /* Allocate bulk transfers. */
unsigned int i;
for (i = 0; i < min(DEDIPROG_ASYNC_TRANSFERS, count); ++i) {
transfers[i] = libusb_alloc_transfer(0);
if (!transfers[i]) {
msg_perr("Allocating libusb transfer %i failed: %s!\n", i, libusb_error_name(ret));
goto err_free;
}
}
/* Now transfer requested chunks using libusb's asynchronous interface. */
while (!status.error && (status.queued_idx < count)) {
while ((status.queued_idx - status.finished_idx) < DEDIPROG_ASYNC_TRANSFERS) {
transfer = transfers[status.queued_idx % DEDIPROG_ASYNC_TRANSFERS];
libusb_fill_bulk_transfer(transfer, dediprog_handle, 0x80 | dediprog_in_endpoint,
(unsigned char *)buf + status.queued_idx * chunksize, chunksize,
dediprog_bulk_read_cb, &status, DEFAULT_TIMEOUT);
transfer->flags |= LIBUSB_TRANSFER_SHORT_NOT_OK;
ret = libusb_submit_transfer(transfer);
if (ret < 0) {
msg_perr("Submitting SPI bulk read %i failed: %s!\n",
status.queued_idx, libusb_error_name(ret));
goto err_free;
}
++status.queued_idx;
}
if (dediprog_bulk_read_poll(&status, 0))
goto err_free;
}
/* Wait for transfers to finish. */
if (dediprog_bulk_read_poll(&status, 1))
goto err_free;
/* Check if everything has been transmitted. */
if ((status.finished_idx < count) || status.error)
goto err_free;
err = 0;
err_free:
dediprog_bulk_read_poll(&status, 1);
for (i = 0; i < DEDIPROG_ASYNC_TRANSFERS; ++i)
if (transfers[i]) libusb_free_transfer(transfers[i]);
return err;
} }
static int dediprog_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len) static int dediprog_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
@ -455,19 +574,20 @@ static int dediprog_spi_bulk_write(struct flashctx *flash, const uint8_t *buf, u
fill_rw_cmd_payload(data_packet, count, dedi_spi_cmd, &value, &idx, start); fill_rw_cmd_payload(data_packet, count, dedi_spi_cmd, &value, &idx, start);
int ret = dediprog_write(CMD_WRITE, value, idx, data_packet, sizeof(data_packet)); int ret = dediprog_write(CMD_WRITE, value, idx, data_packet, sizeof(data_packet));
if (ret != sizeof(data_packet)) { if (ret != sizeof(data_packet)) {
msg_perr("Command Write SPI Bulk failed, %i %s!\n", ret, msg_perr("Command Write SPI Bulk failed, %s!\n", libusb_error_name(ret));
usb_strerror());
return 1; return 1;
} }
unsigned int i; unsigned int i;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
char usbbuf[512]; unsigned char usbbuf[512];
memcpy(usbbuf, buf + i * chunksize, chunksize); memcpy(usbbuf, buf + i * chunksize, chunksize);
memset(usbbuf + chunksize, 0xff, sizeof(usbbuf) - chunksize); // fill up with 0xFF memset(usbbuf + chunksize, 0xff, sizeof(usbbuf) - chunksize); // fill up with 0xFF
ret = usb_bulk_write(dediprog_handle, dediprog_out_endpoint, usbbuf, 512, DEFAULT_TIMEOUT); int transferred;
if (ret != 512) { ret = libusb_bulk_transfer(dediprog_handle, dediprog_out_endpoint, usbbuf, 512, &transferred,
msg_perr("SPI bulk write failed, expected %i, got %i %s!\n", 512, ret, usb_strerror()); DEFAULT_TIMEOUT);
if ((ret < 0) || (transferred != 512)) {
msg_perr("SPI bulk write failed, expected %i, got %s!\n", 512, libusb_error_name(ret));
return 1; return 1;
} }
} }
@ -568,7 +688,7 @@ static int dediprog_spi_send_command(struct flashctx *flash,
ret = dediprog_write(CMD_TRANSCEIVE, value, idx, writearr, writecnt); ret = dediprog_write(CMD_TRANSCEIVE, value, idx, writearr, writecnt);
if (ret != writecnt) { if (ret != writecnt) {
msg_perr("Send SPI failed, expected %i, got %i %s!\n", msg_perr("Send SPI failed, expected %i, got %i %s!\n",
writecnt, ret, usb_strerror()); writecnt, ret, libusb_error_name(ret));
return 1; return 1;
} }
if (readcnt == 0) // If we don't require a response, we are done here if (readcnt == 0) // If we don't require a response, we are done here
@ -584,7 +704,7 @@ static int dediprog_spi_send_command(struct flashctx *flash,
} }
ret = dediprog_read(CMD_TRANSCEIVE, value, idx, readarr, readcnt); ret = dediprog_read(CMD_TRANSCEIVE, value, idx, readarr, readcnt);
if (ret != readcnt) { if (ret != readcnt) {
msg_perr("Receive SPI failed, expected %i, got %i %s!\n", readcnt, ret, usb_strerror()); msg_perr("Receive SPI failed, expected %i, got %i %s!\n", readcnt, ret, libusb_error_name(ret));
return 1; return 1;
} }
return 0; return 0;
@ -640,11 +760,11 @@ static int dediprog_check_devicestring(void)
* than V6.0.0. Newer programmers (including all SF600s) do not support it. */ * than V6.0.0. Newer programmers (including all SF600s) do not support it. */
static int dediprog_set_voltage(void) static int dediprog_set_voltage(void)
{ {
char buf[1] = {0}; unsigned char buf[1] = {0};
int ret = usb_control_msg(dediprog_handle, REQTYPE_OTHER_IN, CMD_SET_VOLTAGE, 0x0, 0x0, int ret = libusb_control_transfer(dediprog_handle, REQTYPE_OTHER_IN, CMD_SET_VOLTAGE, 0x0, 0x0,
buf, 0x1, DEFAULT_TIMEOUT); buf, 0x1, DEFAULT_TIMEOUT);
if (ret < 0) { if (ret < 0) {
msg_perr("Command Set Voltage failed (%s)!\n", usb_strerror()); msg_perr("Command Set Voltage failed (%s)!\n", libusb_error_name(ret));
return 1; return 1;
} }
if ((ret != 1) || (buf[0] != 0x6f)) { if ((ret != 1) || (buf[0] != 0x6f)) {
@ -665,7 +785,7 @@ static int dediprog_standalone_mode(void)
msg_pdbg2("Disabling standalone mode.\n"); msg_pdbg2("Disabling standalone mode.\n");
ret = dediprog_write(CMD_SET_STANDALONE, LEAVE_STANDALONE_MODE, 0, NULL, 0); ret = dediprog_write(CMD_SET_STANDALONE, LEAVE_STANDALONE_MODE, 0, NULL, 0);
if (ret) { if (ret) {
msg_perr("Failed to disable standalone mode: %s\n", usb_strerror()); msg_perr("Failed to disable standalone mode: %s\n", libusb_error_name(ret));
return 1; return 1;
} }
@ -685,7 +805,7 @@ static int dediprog_command_b(void)
ret = usb_control_msg(dediprog_handle, REQTYPE_OTHER_IN, 0x7, 0x0, 0xef00, ret = usb_control_msg(dediprog_handle, REQTYPE_OTHER_IN, 0x7, 0x0, 0xef00,
buf, 0x3, DEFAULT_TIMEOUT); buf, 0x3, DEFAULT_TIMEOUT);
if (ret < 0) { if (ret < 0) {
msg_perr("Command B failed (%s)!\n", usb_strerror()); msg_perr("Command B failed (%s)!\n", libusb_error_name(ret));
return 1; return 1;
} }
if ((ret != 0x3) || (buf[0] != 0xff) || (buf[1] != 0xff) || if ((ret != 0x3) || (buf[0] != 0xff) || (buf[1] != 0xff) ||
@ -700,10 +820,9 @@ static int dediprog_command_b(void)
static int set_target_flash(enum dediprog_target target) static int set_target_flash(enum dediprog_target target)
{ {
int ret = usb_control_msg(dediprog_handle, REQTYPE_EP_OUT, CMD_SET_TARGET, target, 0, int ret = dediprog_write(CMD_SET_TARGET, target, 0, NULL, 0);
NULL, 0, DEFAULT_TIMEOUT);
if (ret != 0) { if (ret != 0) {
msg_perr("set_target_flash failed (%s)!\n", usb_strerror()); msg_perr("set_target_flash failed (%s)!\n", libusb_error_name(ret));
return 1; return 1;
} }
return 0; return 0;
@ -717,7 +836,7 @@ static bool dediprog_get_button(void)
int ret = usb_control_msg(dediprog_handle, REQTYPE_EP_IN, CMD_GET_BUTTON, 0, 0, int ret = usb_control_msg(dediprog_handle, REQTYPE_EP_IN, CMD_GET_BUTTON, 0, 0,
buf, 0x1, DEFAULT_TIMEOUT); buf, 0x1, DEFAULT_TIMEOUT);
if (ret != 0) { if (ret != 0) {
msg_perr("Could not get button state (%s)!\n", usb_strerror()); msg_perr("Could not get button state (%s)!\n", libusb_error_name(ret));
return 1; return 1;
} }
return buf[0] != 1; return buf[0] != 1;
@ -792,20 +911,18 @@ static int dediprog_shutdown(void *data)
if (dediprog_set_spi_voltage(0x0)) if (dediprog_set_spi_voltage(0x0))
return 1; return 1;
if (usb_release_interface(dediprog_handle, 0)) { if (libusb_release_interface(dediprog_handle, 0)) {
msg_perr("Could not release USB interface!\n"); msg_perr("Could not release USB interface!\n");
return 1; return 1;
} }
if (usb_close(dediprog_handle)) { libusb_close(dediprog_handle);
msg_perr("Could not close USB device!\n"); libusb_exit(usb_ctx);
return 1;
}
return 0; return 0;
} }
int dediprog_init(void) int dediprog_init(void)
{ {
struct usb_device *dev;
char *voltage, *device, *spispeed, *target_str; char *voltage, *device, *spispeed, *target_str;
int spispeed_idx = 1; int spispeed_idx = 1;
int millivolt = 3500; int millivolt = 3500;
@ -887,35 +1004,29 @@ int dediprog_init(void)
free(target_str); free(target_str);
/* Here comes the USB stuff. */ /* Here comes the USB stuff. */
usb_init(); libusb_init(&usb_ctx);
usb_find_busses(); if (!usb_ctx) {
usb_find_devices(); msg_perr("Could not initialize libusb!\n");
dev = get_device_by_vid_pid(0x0483, 0xdada, (unsigned int) usedevice);
if (!dev) {
msg_perr("Could not find a Dediprog SF100 on USB!\n");
return 1; return 1;
} }
msg_pdbg("Found USB device (%04x:%04x).\n", dediprog_handle = get_device_by_vid_pid_number(0x0483, 0xdada, (unsigned int) usedevice);
dev->descriptor.idVendor, dev->descriptor.idProduct);
dediprog_handle = usb_open(dev);
if (!dediprog_handle) { if (!dediprog_handle) {
msg_perr("Could not find a Dediprog programmer on USB: %s\n", usb_strerror()); msg_perr("Could not find a Dediprog programmer on USB.\n");
libusb_exit(usb_ctx);
return 1; return 1;
} }
ret = usb_set_configuration(dediprog_handle, 1); ret = libusb_set_configuration(dediprog_handle, 1);
if (ret < 0) { if (ret != 0) {
msg_perr("Could not set USB device configuration: %i %s\n", msg_perr("Could not set USB device configuration: %i %s\n", ret, libusb_error_name(ret));
ret, usb_strerror()); libusb_close(dediprog_handle);
if (usb_close(dediprog_handle)) libusb_exit(usb_ctx);
msg_perr("Could not close USB device!\n");
return 1; return 1;
} }
ret = usb_claim_interface(dediprog_handle, 0); ret = libusb_claim_interface(dediprog_handle, 0);
if (ret < 0) { if (ret < 0) {
msg_perr("Could not claim USB device interface %i: %i %s\n", msg_perr("Could not claim USB device interface %i: %i %s\n", 0, ret, libusb_error_name(ret));
0, ret, usb_strerror()); libusb_close(dediprog_handle);
if (usb_close(dediprog_handle)) libusb_exit(usb_ctx);
msg_perr("Could not close USB device!\n");
return 1; return 1;
} }
@ -959,4 +1070,3 @@ int dediprog_init(void)
return 0; return 0;
} }

View File

@ -1082,11 +1082,11 @@ needs TCP access to the network or userspace access to a serial port.
.B buspirate_spi .B buspirate_spi
needs userspace access to a serial port. needs userspace access to a serial port.
.sp .sp
.BR dediprog ", " ft2232_spi ", " usbblaster_spi " and " pickit2_spi .BR ft2232_spi ", " usbblaster_spi " and " pickit2_spi
need access to the respective USB device via libusb API version 0.1. need access to the respective USB device via libusb API version 0.1.
.sp .sp
.BR ch341a_spi .BR ch341a_spi " and " dediprog
needs access to the respective USB device via libusb API version 1.0. need access to the respective USB device via libusb API version 1.0.
.sp .sp
.B dummy .B dummy
needs no access permissions at all. needs no access permissions at all.

View File

@ -95,9 +95,8 @@ static usb_dev_handle *pickit2_handle;
#define SCR_VDD_OFF 0xFE #define SCR_VDD_OFF 0xFE
#define SCR_VDD_ON 0xFF #define SCR_VDD_ON 0xFF
/* Copied from dediprog.c */ /* Might be useful for other USB devices as well. static for now.
/* Might be useful for other USB devices as well. static for now. */ * device parameter allows user to specify one device of multiple installed */
/* device parameter allows user to specify one device of multiple installed */
static struct usb_device *get_device_by_vid_pid(uint16_t vid, uint16_t pid, unsigned int device) static struct usb_device *get_device_by_vid_pid(uint16_t vid, uint16_t pid, unsigned int device)
{ {
struct usb_bus *bus; struct usb_bus *bus;