diff --git a/src/cmsisDAP.cpp b/src/cmsisDAP.cpp index e627ac6..b46504d 100644 --- a/src/cmsisDAP.cpp +++ b/src/cmsisDAP.cpp @@ -3,6 +3,8 @@ * Copyright (c) 2021 Gwenhael Goavec-Merou */ +#include +#include #include #include #include @@ -87,15 +89,76 @@ enum cmsisdap_status { DAP_ERROR = 0xff }; -CmsisDAP::CmsisDAP(const cable_t &cable, int index, int8_t verbose):_verbose(verbose>0), - _device_idx(0), _vid(cable.vid), _pid(cable.pid), - _serial_number(L""), _dev(NULL), _num_tms(0), _is_connect(false) +CmsisDAP::CmsisDAP(const cable_t &cable, int index, uint32_t clkHZ, int8_t verbose, int backend):_verbose(verbose>0), + _device_idx(0), _vid(cable.vid), _pid(cable.pid), _serial_number(L""), + _hid_dev(NULL), _usb_dev(NULL), _ctx(NULL), _packet_size(0), + _ep_in(0), _ep_out(0), _num_tms(0), _is_connect(false), _backend(backend) { - std::vector dev_found; - _ll_buffer = (unsigned char *)malloc(sizeof(unsigned char) * 65); + _ll_buffer = (unsigned char *)malloc(sizeof(unsigned char) * 1024); if (!_ll_buffer) throw std::runtime_error("internal buffer allocation failed"); _buffer = _ll_buffer+2; + switch (backend){ + case BACKEND_HID: + initWithHID(cable, index, verbose); + break; + case BACKEND_USBBULK: + initWithBulk(cable, verbose); + break; + case BACKEND_AUTOSELECT: + char t[256]; + try { + _backend = BACKEND_HID; + initWithHID(cable, index, verbose); + break; + } catch (std::runtime_error const& e) { + snprintf(t, sizeof(t), "try HID init but failed with: %s", e.what()); + printInfo(t); + } + try { + _backend = BACKEND_USBBULK; + initWithBulk(cable, verbose); + break; + } catch (std::runtime_error const& e) { + snprintf(t, sizeof(t), "try USB bulk init but failed with: %s", e.what()); + printInfo(t); + } + throw std::runtime_error("Error: no USB backend available"); + break; + default: + throw std::runtime_error("Error: unknown USB backend"); + break; + } + if (clkHZ > 0) + setClkFreq(clkHZ); +} + +CmsisDAP::~CmsisDAP() +{ + /* disconnect and close device + * and free context + */ + switch(_backend){ + case BACKEND_HID: + if (_is_connect) + dapDisconnect(); + if (_hid_dev) + hid_close(_hid_dev); + hid_exit(); + break; + case BACKEND_USBBULK: + libusb_close(_usb_dev); + libusb_exit(_ctx); + break; + default: + break; + } + if (_ll_buffer) + free(_ll_buffer); +} + +void CmsisDAP::initWithHID(const cable_t &cable, int index, int8_t verbose){ + std::vector dev_found; /* only hid support */ struct hid_device_info *devs, *cur_dev; @@ -157,11 +220,13 @@ CmsisDAP::CmsisDAP(const cable_t &cable, int index, int8_t verbose):_verbose(ver /* store params about device to use */ _vid = dev_found[_device_idx]->vendor_id; _pid = dev_found[_device_idx]->product_id; + _vendor = dev_found[_device_idx]->manufacturer_string; + _product_name = dev_found[_device_idx]->product_string; if (dev_found[_device_idx]->serial_number != NULL) _serial_number = std::wstring(dev_found[_device_idx]->serial_number); /* open the device */ - _dev = hid_open_path(dev_found[_device_idx]->path); - if (!_dev) { + _hid_dev = hid_open_path(dev_found[_device_idx]->path); + if (!_hid_dev) { throw std::runtime_error( std::string("Couldn't open device. Check permissions for ") + dev_found[_device_idx]->path); } @@ -206,7 +271,7 @@ CmsisDAP::CmsisDAP(const cable_t &cable, int index, int8_t verbose):_verbose(ver memset(_buffer, 0, 63); int res = read_info(INFO_ID_HWCAP, _buffer, 63); if (res < 0) { - hid_close(_dev); + hid_close(_hid_dev); hid_exit(); char t[256]; snprintf(t, sizeof(t), "Error %d for command %d\n", res, INFO_ID_HWCAP); @@ -216,34 +281,260 @@ CmsisDAP::CmsisDAP(const cable_t &cable, int index, int8_t verbose):_verbose(ver if (verbose) printf("Hardware cap %02x %02x %02x\n", _buffer[0], _buffer[1], _buffer[2]); if (!(_buffer[2] & (1 << 1))) { - hid_close(_dev); + hid_close(_hid_dev); hid_exit(); throw std::runtime_error("JTAG is not supported by the probe"); } /* send connect */ if (dapConnect() != 1) { - hid_close(_dev); + hid_close(_hid_dev); hid_exit(); throw std::runtime_error("DAP connection in JTAG mode failed"); } + + printInfo("HID init successful"); } -CmsisDAP::~CmsisDAP() -{ - /* disconnect and close device - * and free context - */ - if (_is_connect) - dapDisconnect(); - if (_dev) - hid_close(_dev); - hid_exit(); +void CmsisDAP::initWithBulk(const cable_t &cable, int8_t verbose){ + struct libusb_device **devs, *cur_dev; - if (_ll_buffer) - free(_ll_buffer); + if (libusb_init(&_ctx) != 0){ + throw std::runtime_error("libusb init failed"); + } + + int devs_len = libusb_get_device_list(_ctx, &devs); + if (devs_len <= 0) { + libusb_exit(_ctx); + throw std::runtime_error("No device found"); + } + + std::vector devs_desc; + for(int i = 0; i < devs_len; i++){ + struct libusb_device *dev = devs[i]; + struct libusb_device_descriptor dev_desc; + + if(libusb_get_device_descriptor(dev, &dev_desc) != 0){ + printWarn("could not get device descriptor for device " + std::to_string(i)); + continue; + } + + if(dev_desc.idVendor == cable.vid && dev_desc.idProduct == cable.pid){ + devs_desc.push_back(&dev_desc); + cur_dev = dev; + break; + } + } + + if (devs_desc.size() <= 0) { + libusb_exit(_ctx); + throw std::runtime_error( + "Error: failed to find compatiable device from list"); + } + if (devs_desc.size() > 1) { + libusb_exit(_ctx); + throw std::runtime_error( + "Error: more than one device. Please provide VID/PID"); + } + + printInfo("Found " + std::to_string(devs_desc.size()) + " compatible device:"); + for (size_t i = 0; i < devs_desc.size(); i++) { + char val[256]; + snprintf(val, sizeof(val), "\t0x%04x 0x%04x", + devs_desc[i]->idVendor, + devs_desc[i]->idProduct); + // TODO: retrieve product and vendor strings right here, if possible + printInfo(val); + } + + libusb_device_descriptor *cur_desc = devs_desc[_device_idx]; + _vid = cur_desc->idVendor; + _pid = cur_desc->idProduct; + + /* open the device */ + int ret = libusb_open(cur_dev, &_usb_dev); + if (ret != 0 || !_usb_dev) { + char t[256]; + snprintf(t, sizeof(t), "Could not open device 0x%04x:0x%04x", _vid, _pid); + throw std::runtime_error(t); + } + + char serial[256] = {0}; + if(libusb_get_string_descriptor_ascii(_usb_dev, cur_desc->iSerialNumber, (uint8_t *) serial, sizeof(serial)) < 0){ + char t[256]; + snprintf(t, sizeof(t), "could not read serial number for device 0x%04x:0x%04x", _vid, _pid); + printWarn(t); + } else { + _serial_number = std::wstring(serial, serial + std::strlen(serial)); + } + + char vendor[256] = {0}; + if(libusb_get_string_descriptor_ascii(_usb_dev, cur_desc->iManufacturer, (uint8_t *) vendor, sizeof(vendor)) < 0){ + char t[256]; + snprintf(t, sizeof(t), "could not read serial number for device 0x%04x:0x%04x", _vid, _pid); + printWarn(t); + } else { + _vendor = std::wstring(vendor, vendor + std::strlen(vendor)); + } + + char product_string[256] = {0}; + if(libusb_get_string_descriptor_ascii(_usb_dev, cur_desc->iProduct, (uint8_t *) product_string, sizeof(product_string)) < 0){ + char t[256]; + snprintf(t, sizeof(t), "could not read product string for device 0x%04x:0x%04x", _vid, _pid); + printWarn(t); + } else { + _product_name = std::wstring(product_string, product_string + std::strlen(product_string)); + if (!std::strstr(product_string, "CMSIS-DAP")){ + // CMSIS-DAP spec mandates that the string "CMSIS-DAP" is present in the product string + char t[256]; + snprintf(t, sizeof(t), "device 0x%04x:0x%04x does not appear to be a CMSIS-DAP device", _vid, _pid); + throw std::runtime_error(t); + } + } + + for (int config = 0; config < cur_desc->bNumConfigurations; config++) { + struct libusb_config_descriptor *config_desc; + if (libusb_get_config_descriptor(cur_dev, config, &config_desc) != 0) { + char t[256]; + snprintf(t, sizeof(t), "could not get configuration descriptor %d for device 0x%04x:0x%04x", config, _vid, _pid); + printError(t); + continue; + } + + int config_num = config_desc->bConfigurationValue; + const struct libusb_interface_descriptor *intf_desc_found = NULL; + + for (int interface = 0; interface < config_desc->bNumInterfaces; interface++) { + const struct libusb_interface_descriptor *intf_desc = &config_desc->interface[interface].altsetting[0]; + int interface_num = intf_desc->bInterfaceNumber; + + /* Search for "CMSIS-DAP" in the interface string */ + bool interface_str_valid = false; + if (intf_desc->iInterface != 0) { + char interface_str[256] = {0}; + if(libusb_get_string_descriptor_ascii(_usb_dev, intf_desc->iInterface, (uint8_t *)interface_str, sizeof(interface_str)) < 0){ + char t[256]; + snprintf(t, sizeof(t), "could not read interface string for device 0x%04x:0x%04x", _vid, _pid); + printWarn(t); + } else if (!std::strstr(interface_str, "CMSIS-DAP")){ + interface_str_valid = true; + } + } + + if (intf_desc->bNumEndpoints < 2 || + (intf_desc->endpoint[0].bmAttributes & 3) != LIBUSB_TRANSFER_TYPE_BULK || + (intf_desc->endpoint[0].bEndpointAddress & 0x80) != LIBUSB_ENDPOINT_OUT || + (intf_desc->endpoint[1].bmAttributes & 3) != LIBUSB_TRANSFER_TYPE_BULK || + (intf_desc->endpoint[1].bEndpointAddress & 0x80) != LIBUSB_ENDPOINT_IN){ + continue; + } + + if (intf_desc->bInterfaceClass != LIBUSB_CLASS_VENDOR_SPEC || + intf_desc->bInterfaceSubClass != 0 || intf_desc->bInterfaceProtocol != 0) { + /* If the interface is reliably identified + * then we need not insist on setting USB class, subclass and protocol + * exactly as the specification requires. + * Just filter out the well known classes, mainly CDC and MSC. + * At least KitProg3 uses class 0 contrary to the specification */ + char t[256]; + if (interface_str_valid && + (intf_desc->bInterfaceClass == 0 || intf_desc->bInterfaceClass > 0x12)) { + snprintf(t, sizeof(t), "Using interface %d with wrong class %d, subclass %d or protocol %d", + interface_num, + intf_desc->bInterfaceClass, + intf_desc->bInterfaceSubClass, + intf_desc->bInterfaceProtocol); + printWarn(t); + } else { + continue; + } + } + intf_desc_found = intf_desc; + } + + if (!intf_desc_found) { + libusb_free_config_descriptor(config_desc); + char t[256]; + snprintf(t, sizeof(t), "could not find correct interface descriptor for device 0x%04x:0x%04x", _vid, _pid); + printError(t); + continue; + } + + int interface_num = intf_desc_found->bInterfaceNumber; + _packet_size = intf_desc_found->endpoint[0].wMaxPacketSize; + _ep_out = intf_desc_found->endpoint[0].bEndpointAddress; + _ep_in = intf_desc_found->endpoint[1].bEndpointAddress; + + libusb_free_device_list(devs, true); + libusb_free_config_descriptor(config_desc); + + int current_config; + if (libusb_get_configuration(_usb_dev, ¤t_config) != 0){ + throw std::runtime_error("could not find current configuration"); + } + + if (config_num != current_config) { + int ret = libusb_set_configuration(_usb_dev, config_desc->bConfigurationValue); + if(ret != 0 && ret != LIBUSB_ERROR_NOT_SUPPORTED){ + throw std::runtime_error("could not set current configuration"); + } + } + + if (libusb_claim_interface(_usb_dev, interface_num) != 0){ + throw std::runtime_error("could not claim interface"); + } + + if (!libusb_dev_mem_alloc(_usb_dev, _packet_size)){ + throw std::runtime_error("failed to alloc DMA memory for device"); + } + + if (verbose) { + display_info(INFO_ID_VID , DAPLINK_INFO_STRING); + display_info(INFO_ID_PID , DAPLINK_INFO_STRING); + display_info(INFO_ID_SERNUM , DAPLINK_INFO_STRING); + display_info(INFO_ID_FWVERS , DAPLINK_INFO_STRING); + display_info(INFO_ID_TARGET_DEV_VENDOR , DAPLINK_INFO_STRING); + display_info(INFO_ID_TARGET_DEV_NAME , DAPLINK_INFO_STRING); + display_info(INFO_ID_HWCAP , DAPLINK_INFO_BYTE); + display_info(INFO_ID_SWO_TRACE_BUF_SIZE, DAPLINK_INFO_WORD); + display_info(INFO_ID_MAX_PKT_CNT , DAPLINK_INFO_BYTE); + display_info(INFO_ID_MAX_PKT_SZ , DAPLINK_INFO_SHORT); + } + + memset(_buffer, 0, 63); + int res = read_info(INFO_ID_HWCAP, _buffer, 63); + if (res < 0) { + libusb_close(_usb_dev); + libusb_exit(_ctx); + char t[256]; + snprintf(t, sizeof(t), "Error %d for command %d\n", res, INFO_ID_HWCAP); + throw std::runtime_error(t); + } + + if (verbose) + printf("Hardware cap %02x %02x %02x\n", _buffer[0], _buffer[1], _buffer[2]); + if (!(_buffer[2] & (1 << 1))) { + libusb_close(_usb_dev); + libusb_exit(_ctx); + throw std::runtime_error("JTAG is not supported by the probe"); + } + + /* send connect */ + if (dapConnect() != 1) { + libusb_close(_usb_dev); + libusb_exit(_ctx); + throw std::runtime_error("DAP connection in JTAG mode failed"); + } + + printInfo("USB bulk init successful"); + return; + } + + libusb_free_device_list(devs, true); + libusb_exit(_ctx); + + throw std::runtime_error("failed to initialize USB bulk device"); } - /* send connect instruction (0x02) to switch * in JTAG mode (0x02) */ @@ -504,34 +795,59 @@ int CmsisDAP::flush() int CmsisDAP::xfer(uint8_t instruction, int tx_len, uint8_t *rx_buff, int rx_len) { - (void)tx_len; - + int ret = -1, bulk_len = 0; _ll_buffer[0] = 0; _ll_buffer[1] = instruction; - int ret = hid_write(_dev, _ll_buffer, 65); - if (ret == -1) { - printf("Error\n"); - return ret; + switch(_backend){ + case BACKEND_HID: + ret = hid_write(_hid_dev, _ll_buffer, 65); + if (ret == -1) { + printError("Error: HID write failed\n"); + return ret; + } + ret = hid_read_timeout(_hid_dev, _ll_buffer, 65, 1000); + if (ret <= 0) { + if (ret == 0) + printError("Error: HID read timeout\n"); + else if (ret == -1) + printError("Error: HID comm failed\n"); + return ret; + } + break; + case BACKEND_USBBULK: + ret = libusb_bulk_transfer(_usb_dev, _ep_out, &_ll_buffer[1], tx_len + 1, &bulk_len, 1000); + if (ret != 0) { + printError("Error: Bulk write failed\n"); + return ret; + } + ret = libusb_bulk_transfer(_usb_dev, _ep_in, &_ll_buffer[0], _packet_size, &bulk_len, 1000); + if (ret != 0 && ret != LIBUSB_ERROR_TIMEOUT) { + printError("Error: Bulk read failed\n"); + return ret; + } + if(bulk_len == 0){ + printError("Error: Bulk timeout"); + return -1; + } + ret = bulk_len; + break; + default: + printError("Error: unknown USB backend"); + break; } - ret = hid_read_timeout(_dev, _ll_buffer, 65, 1000); - if (ret <= 0) { - if (ret == 0) - printError("Error timeout\n"); - else if (ret == -1) - printError("Error comm\n"); - return ret; - } - if (_ll_buffer[0] != instruction && _ll_buffer[1] != DAP_OK) { - printf("Error: command error"); + if (_ll_buffer[0] != instruction) { + printError("Error: command error"); + return -1; + } + if (_ll_buffer[1] != DAP_OK) { + printError("Error: DAP status error"); return -1; } - if (rx_buff) { memcpy(rx_buff, _buffer, rx_len); } - return ret; } @@ -541,28 +857,50 @@ int CmsisDAP::xfer(uint8_t instruction, int tx_len, */ int CmsisDAP::xfer(int tx_len, uint8_t *rx_buff, int rx_len) { - (void)tx_len; - + int ret = -1, bulk_len = 0; _ll_buffer[0] = 0; - int ret = hid_write(_dev, _ll_buffer, 65); - if (ret == -1) { - printf("Error\n"); - return ret; + switch(_backend){ + case BACKEND_HID: + ret = hid_write(_hid_dev, _ll_buffer, 65); + if (ret == -1) { + printError("Error: HID write failed\n"); + return ret; + } + ret = hid_read_timeout(_hid_dev, _ll_buffer, 65, 1000); + if (ret <= 0) { + if (ret == 0) + printError("Error: HID read timeout\n"); + else if (ret == -1) + printError("Error: HID comm failed\n"); + return ret; + } + break; + case BACKEND_USBBULK: + ret = libusb_bulk_transfer(_usb_dev, _ep_out, &_ll_buffer[1], tx_len, &bulk_len, 1000); + if (ret != 0) { + printError("Error: Bulk write failed\n"); + return ret; + } + ret = libusb_bulk_transfer(_usb_dev, _ep_in, &_ll_buffer[0], _packet_size, &bulk_len, 1000); + if (ret != 0 && ret != LIBUSB_ERROR_TIMEOUT) { + printError("Error: Bulk read failed\n"); + return ret; + } + if(bulk_len == 0){ + printError("Error: Bulk timeout"); + return -1; + } + ret = bulk_len; + break; + default: + printError("Error: unknown USB backend"); + break; } - ret = hid_read_timeout(_dev, _ll_buffer, 65, 1000); - if (ret <= 0) { - if (ret == 0) - printf("Error timeout\n"); - else if (ret == -1) - printf("Error comm\n"); - return ret; - } if (rx_len) memmove(rx_buff, _ll_buffer, rx_len); - return ret; } @@ -590,24 +928,36 @@ void CmsisDAP::display_info(uint8_t info, uint8_t type) if (ret == 0) { char val[256]; if (info == INFO_ID_VID) { - snprintf(val, sizeof(val), "\t%s: %04x", + snprintf(val, sizeof(val), "\t%s : %04x", cmsisdap_info_id_str[info].c_str(), _vid); } else if (info == INFO_ID_PID) { - snprintf(val, sizeof(val), "\t%s: %04x", + snprintf(val, sizeof(val), "\t%s : %04x", cmsisdap_info_id_str[info].c_str(), _pid); } else if (info == INFO_ID_SERNUM) { if (!_serial_number.empty()) { - snprintf(val, sizeof(val), "\t%s: %ls", + snprintf(val, sizeof(val), "\t%s : %ls", cmsisdap_info_id_str[info].c_str(), _serial_number.c_str()); } else { printError("\t" + cmsisdap_info_id_str[info] + " : NA"); return; } - } else if (info == INFO_ID_TARGET_DEV_NAME || \ - info == INFO_ID_TARGET_DEV_VENDOR) { - /* nothing */ - return; + } else if (info == INFO_ID_TARGET_DEV_NAME) { + if (!_product_name.empty()){ + snprintf(val, sizeof(val), "\t%s : %ls", + cmsisdap_info_id_str[info].c_str(), _product_name.c_str()); + } else { + printError("\t" + cmsisdap_info_id_str[info] + " : NA"); + return; + } + } else if (info == INFO_ID_TARGET_DEV_VENDOR) { + if (!_vendor.empty()){ + snprintf(val, sizeof(val), "\t%s : %ls", + cmsisdap_info_id_str[info].c_str(), _vendor.c_str()); + } else { + printError("\t" + cmsisdap_info_id_str[info] + " : NA"); + return; + } } else { printError("\t" + cmsisdap_info_id_str[info] + " : NA"); return; diff --git a/src/cmsisDAP.hpp b/src/cmsisDAP.hpp index 59933d7..48cf7e4 100644 --- a/src/cmsisDAP.hpp +++ b/src/cmsisDAP.hpp @@ -15,6 +15,12 @@ #include "cable.hpp" #include "jtagInterface.hpp" +enum cmsisdap_backend_type { + BACKEND_AUTOSELECT = -1, + BACKEND_HID = 0, + BACKEND_USBBULK = 1, +}; + class CmsisDAP: public JtagInterface { public: /*! @@ -23,9 +29,11 @@ class CmsisDAP: public JtagInterface { * \param[in] vid: vendor id * \param[in] pid: product id * \param[in] index: interface number - * \param[in] verbose: verbose level 0 normal, 1 verbose + * \param[in] clkHZ: clock frequency + * \param[in] verbose: verbose level (0 normal, 1 verbose) + * \param[in] backend: backend type (0 HID, 1 USB bulk) */ - CmsisDAP(const cable_t &cable, int index, int8_t verbose); + CmsisDAP(const cable_t &cable, int index, uint32_t clkHZ, int8_t verbose, int backend); ~CmsisDAP(); @@ -48,7 +56,7 @@ class CmsisDAP: public JtagInterface { /*! * \brief write and read len bits with optional tms set to 1 if end - * \param[in] tx: serie of tdi state to send + * \param[in] tx: serie of tdi state to send * \param[out] rx: buffer to store tdo bits from device * \param[in] len: number of bit to read/write * \param[in] end: if true tms is set to one with the last tdi bit @@ -89,6 +97,9 @@ class CmsisDAP: public JtagInterface { */ int dapDisconnect(); int dapResetTarget(); + + void initWithHID(const cable_t &cable, int index, int8_t verbose); + void initWithBulk(const cable_t &cable, int8_t verbose); int read_info(uint8_t info, uint8_t *rd_info, int max_len); int xfer(int tx_len, uint8_t *rx_buff, int rx_len); int xfer(uint8_t instruction, int tx_len, @@ -103,13 +114,20 @@ class CmsisDAP: public JtagInterface { uint16_t _vid; /**< device Vendor ID */ uint16_t _pid; /**< device Product ID */ std::wstring _serial_number; /**< device serial number */ + std::wstring _vendor; /**< device manufacturer */ + std::wstring _product_name; /**< device product name */ - hid_device *_dev; /**< hid device used to communicate */ - + hid_device *_hid_dev; /**< hid device used to communicate */ + libusb_device_handle *_usb_dev; /**< libusb device used to communicate */ + libusb_context *_ctx; /**< libusb context */ unsigned char *_ll_buffer; /**< message buffer */ unsigned char *_buffer; /**< subset of _ll_buffer */ + int _packet_size; /**< USB bulk packet size */ + int _ep_in; /**< USB bulk in endpoint */ + int _ep_out; /**< USB bulk out endpoint */ int _num_tms; /**< current tms length */ int _is_connect; /**< device status ((dis)connected) */ + int _backend; /**< type of USB backend */ }; #endif // SRC_CMSISDAP_HPP_ diff --git a/src/jtag.cpp b/src/jtag.cpp index b5ed9a5..79cabb4 100644 --- a/src/jtag.cpp +++ b/src/jtag.cpp @@ -93,7 +93,7 @@ */ Jtag::Jtag(const cable_t &cable, const jtag_pins_conf_t *pin_conf, - const std::string &dev, + const std::string &dev, int backend, const std::string &serial, uint32_t clkHZ, int8_t verbose, const std::string &ip_adr, int port, const bool invert_read_edge, const std::string &firmware_path, @@ -178,7 +178,7 @@ Jtag::Jtag(const cable_t &cable, const jtag_pins_conf_t *pin_conf, #endif case MODE_CMSISDAP: #ifdef ENABLE_CMSISDAP - _jtag = new CmsisDAP(cable, cable.config.index, verbose); + _jtag = new CmsisDAP(cable, cable.config.index, clkHZ, verbose, backend); break; #else std::cerr << "Jtag: support for cmsisdap was not enabled at compile time" << std::endl; diff --git a/src/jtag.hpp b/src/jtag.hpp index 15fdfee..a5ca27e 100644 --- a/src/jtag.hpp +++ b/src/jtag.hpp @@ -20,7 +20,7 @@ class Jtag { public: Jtag(const cable_t &cable, const jtag_pins_conf_t *pin_conf, - const std::string &dev, + const std::string &dev, int backend, const std::string &serial, uint32_t clkHZ, int8_t verbose, const std::string &ip_adr, int port, const bool invert_read_edge = false,