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:
parent
c05900f3dc
commit
d99a2bd049
2
Makefile
2
Makefile
@ -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)
|
||||||
|
286
dediprog.c
286
dediprog.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user