From ea613fa97af89c3ee0e8ef8b8b1865c22a100d13 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Sun, 3 Oct 2021 12:39:06 +0200 Subject: [PATCH] dfu/main: add args to select altsetting and add filter to select corresponding interface --- README.md | 1 + src/board.hpp | 9 +++++---- src/dfu.cpp | 15 ++++++++++++--- src/dfu.hpp | 10 +++++++++- src/main.cpp | 14 ++++++++++++-- 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index a49d9b4..e1e6053 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ openFPGALoader --help Usage: openFPGALoader [OPTION...] BIT_FILE openFPGALoader -- a program to flash FPGA + --altsetting arg DFU interface altsetting (only for DFU mode) --bitstream arg bitstream -b, --board arg board name, may be used instead of cable -c, --cable arg jtag interface diff --git a/src/board.hpp b/src/board.hpp index 65a845f..59e8863 100644 --- a/src/board.hpp +++ b/src/board.hpp @@ -83,6 +83,7 @@ typedef struct { uint32_t default_freq; /* Default clock speed: 0 = use cable default */ uint16_t vid; /* optional VID: used only with DFU */ uint16_t pid; /* optional VID: used only with DFU */ + uint16_t altsetting; /* optional altsetting: used only with DFU */ } target_board_t; #define CABLE_DEFAULT 0 @@ -96,8 +97,8 @@ typedef struct { #define SPI_BOARD(_name, _manufacturer, _cable, _rst, _done, _cs, _sck, _si, _so, _holdn, _wpn, _freq) \ {_name, {_manufacturer, _cable, "", _rst, _done, COMM_SPI, {}, \ {_cs, _sck, _so, _si, _holdn, _wpn}, _freq, 0, 0}} -#define DFU_BOARD(_name, _fpga_part, _cable, _vid, _pid) \ - {_name, {"", _cable, _fpga_part, 0, 0, COMM_DFU, {}, {}, 0, _vid, _pid}} +#define DFU_BOARD(_name, _fpga_part, _cable, _vid, _pid, _alt) \ + {_name, {"", _cable, _fpga_part, 0, 0, COMM_DFU, {}, {}, 0, _vid, _pid, _alt}} static std::map board_list = { JTAG_BOARD("acornCle215", "xc7a200tsbg484", "", 0, 0, CABLE_DEFAULT), @@ -117,7 +118,7 @@ static std::map board_list = { JTAG_BOARD("ecp5_evn", "", "ft2232", 0, 0, CABLE_DEFAULT), SPI_BOARD("fireant", "efinix", "ft232", DBUS4, DBUS5, DBUS3, DBUS0, DBUS1, DBUS2, DBUS6, 0, CABLE_DEFAULT), - DFU_BOARD("fomu", "", "dfu", 0x1209, 0x5bf0), + DFU_BOARD("fomu", "", "dfu", 0x1209, 0x5bf0, 0), /* most ice40 boards uses the same pinout */ SPI_BOARD("ice40_generic", "lattice", "ft2232", DBUS7, DBUS6, @@ -132,7 +133,7 @@ static std::map board_list = { JTAG_BOARD("spartanEdgeAccelBoard", "", "",0, 0, CABLE_DEFAULT), JTAG_BOARD("pipistrello", "xc6slx45csg324", "ft2232", 0, 0, CABLE_DEFAULT), JTAG_BOARD("minispartan6", "", "ft2232", 0, 0, CABLE_DEFAULT), - DFU_BOARD("orangeCrab", "", "dfu", 0x1209, 0x5af0), + DFU_BOARD("orangeCrab", "", "dfu", 0x1209, 0x5af0, 0), JTAG_BOARD("qmtechCycloneV", "5ce223", "", 0, 0, CABLE_DEFAULT), JTAG_BOARD("runber", "", "ft232", 0, 0, CABLE_DEFAULT), JTAG_BOARD("tangnano", "", "ft2232", 0, 0, CABLE_DEFAULT), diff --git a/src/dfu.cpp b/src/dfu.cpp index 8a4d055..ad73bf7 100644 --- a/src/dfu.cpp +++ b/src/dfu.cpp @@ -47,8 +47,10 @@ enum dfu_cmd { */ DFU::DFU(const string &filename, uint16_t vid, uint16_t pid, + int altsetting, int verbose_lvl):_verbose(verbose_lvl > 0), _quiet(verbose_lvl < 0), dev_idx(0), _vid(0), _pid(0), + _altsetting(altsetting), usb_ctx(NULL), dev_handle(NULL), curr_intf(0), transaction(0), _bit(NULL) { @@ -324,6 +326,8 @@ int DFU::searchIfDFU(struct libusb_device_handle *handle, const struct libusb_interface_descriptor *intf = &uif->altsetting[intf_idx]; uint8_t intfClass = intf->bInterfaceClass; uint8_t intfSubClass = intf->bInterfaceSubClass; + if (_altsetting != -1 && _altsetting != intf_idx) + continue; if (intfClass == 0xfe && intfSubClass == 0x01) { struct dfu_dev my_dev; if (_verbose) @@ -335,6 +339,7 @@ int DFU::searchIfDFU(struct libusb_device_handle *handle, continue; // not compatible my_dev.vid = desc->idVendor; my_dev.pid = desc->idProduct; + my_dev.altsettings = intf_idx; my_dev.interface = if_idx; my_dev.bus = libusb_get_bus_number(dev); my_dev.device = libusb_get_device_address(dev); @@ -342,6 +347,8 @@ int DFU::searchIfDFU(struct libusb_device_handle *handle, libusb_get_string_descriptor_ascii(handle, desc->iProduct, my_dev.iProduct, 128); + libusb_get_string_descriptor_ascii(handle, intf->iInterface, + my_dev.iInterface, 128); int r = libusb_get_port_numbers(dev, my_dev.path, sizeof(my_dev.path)); my_dev.path[r] = '\0'; @@ -566,13 +573,15 @@ void DFU::displayDFU() /* display dfu device */ printf("Found DFU:\n"); for (unsigned int i = 0; i < dfu_dev.size(); i++) { - printf("%04x:%04x (bus %d, device %2d)", + printf("%04x:%04x (bus %d, device %2d),", dfu_dev[i].vid, dfu_dev[i].pid, dfu_dev[i].bus, dfu_dev[i].device); - printf(" path: %d: iProduct %s", dfu_dev[i].path[0], - dfu_dev[i].iProduct); + printf(" path: %d",dfu_dev[i].path[0]); for (size_t j = 1; j < strlen(((const char *)dfu_dev[i].path)); j++) printf(".%d", dfu_dev[i].path[j]); + printf(", alt: %d, iProduct \"%s\", iInterface \"%s\"", + dfu_dev[i].altsettings, + dfu_dev[i].iProduct, dfu_dev[i].iInterface); printf("\n"); printf("\tDFU details\n"); printf("\t\tbLength %02x\n", dfu_dev[i].dfu_desc.bLength); diff --git a/src/dfu.hpp b/src/dfu.hpp index 4fa474d..574a688 100644 --- a/src/dfu.hpp +++ b/src/dfu.hpp @@ -18,9 +18,14 @@ class DFU { public: /*! * \brief contructor + * \param[in] filename: bitstream + * \param[in] vid: vendor id + * \param[in] pid: product id + * \param[in] altsetting: device altsetting to use * \param[in] verbose_lvl: verbose level 0 normal, -1 quiet, 1 verbose */ - DFU(const std::string &filename, uint16_t vid, uint16_t pid, int verbose_lvl); + DFU(const std::string &filename, uint16_t vid, uint16_t pid, + int altsetting, int verbose_lvl); ~DFU(); @@ -59,9 +64,11 @@ class DFU { uint16_t pid; uint8_t bus; uint8_t interface; + uint16_t altsettings; uint8_t device; uint8_t path[8]; uint8_t iProduct[128]; + uint8_t iInterface[128]; uint32_t bMaxPacketSize0; struct dfu_desc dfu_desc; }; @@ -226,6 +233,7 @@ class DFU { int dev_idx; /**< device index in dfu_dev */ uint16_t _vid; /**< device Vendor ID */ uint16_t _pid; /**< device Product ID */ + int16_t _altsetting; /**< device altesetting */ struct libusb_context *usb_ctx; /**< usb context */ libusb_device_handle * dev_handle; /**< current device handle */ int curr_intf; /**< device interface to use */ diff --git a/src/main.cpp b/src/main.cpp index 6ac9c83..080405a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,6 +59,7 @@ struct arguments { int index_chain; unsigned int file_size; bool external_flash; + int altsetting; }; int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *pins_config); @@ -74,7 +75,7 @@ int main(int argc, char **argv) /* command line args. */ struct arguments args = {0, false, false, false, 0, "", "", "-", "", -1, 0, "-", false, false, false, false, Device::WR_SRAM, false, - false, false, "", "", "", -1, 0, false}; + false, false, "", "", "", -1, 0, false, -1}; /* parse arguments */ try { if (parse_opt(argc, argv, &args, &pins_config)) @@ -267,12 +268,19 @@ int main(int argc, char **argv) /* try to init DFU probe */ DFU *dfu = NULL; uint16_t vid = 0, pid = 0; + int altsetting = -1; if (board) { vid = board->vid; pid = board->pid; + altsetting = board->altsetting; + } + if (args.altsetting != -1) { + if (altsetting != -1) + printInfo("Board altsetting overridden"); + altsetting = args.altsetting; } try { - dfu = new DFU(args.bit_file, vid, pid, args.verbose); + dfu = new DFU(args.bit_file, vid, pid, altsetting, args.verbose); } catch (std::exception &e) { printError("DFU init failed with: " + string(e.what())); return EXIT_FAILURE; @@ -486,6 +494,8 @@ int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *p options .add_options() + ("altsetting", "DFU interface altsetting (only for DFU mode)", + cxxopts::value(args->altsetting)) ("bitstream", "bitstream", cxxopts::value(args->bit_file)) ("b,board", "board name, may be used instead of cable",