From d219ea135de599a956e2ff077c468d1d77b1804c Mon Sep 17 00:00:00 2001 From: Claudio Lanconelli Date: Mon, 6 Jan 2025 01:31:18 +0100 Subject: [PATCH] included ftdipp lybrary to avoid dependencies (removed boost dependency) --- CMakeLists.txt | 53 +--- SrcPony/CMakeLists.txt | 2 + SrcPony/ftdi.cpp | 704 +++++++++++++++++++++++++++++++++++++++++ SrcPony/ftdi.hpp | 222 +++++++++++++ ponyprog.pro | 12 +- 5 files changed, 942 insertions(+), 51 deletions(-) create mode 100644 SrcPony/ftdi.cpp create mode 100644 SrcPony/ftdi.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7600e44a..abf08164 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,7 +80,6 @@ SET(CURRENT_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) INCLUDE(FindLibUSB-1.0) - IF(NOT ${LIBUSB_VERSION} LESS "1.0.16") MESSAGE(STATUS "LibUSB version ${LIBUSB_VERSION}") ELSE() @@ -137,12 +136,7 @@ SET(PONYPROG_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) # SET(PONYPROG_ENABLE_SYMBOL_VISIBILITY_DEFAULT OFF) # ENDIF(MSVC) -IF (CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -fno-exceptions") -ELSE() - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-exceptions") -ENDIF() - +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-exceptions") # options for gprof IF(${USE_PROFILER}) @@ -158,16 +152,6 @@ ENDIF() -IF(${USE_QT_VERSION} MATCHES "4") - SET(HAVE_QT_PRINTSUPPORT true) - FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui REQUIRED) - - IF(NOT QT4_FOUND) - MESSAGE(FATAL_ERROR "Qt4 could not be found. " - "If it's INSTALLed in a non-standard location, specify the path to qmake in QT_QMAKE_EXECUTABLE. " - "You can do it in interactive mode (ccmake instead of cmake) or using -DVAR=VAL syntax.") - ENDIF() -ELSE() FIND_PACKAGE(Qt5 COMPONENTS Core PrintSupport Gui Widgets Multimedia REQUIRED QUIET) IF(NOT Qt5Widgets_FOUND) @@ -185,19 +169,18 @@ ELSE() MESSAGE(FATAL_ERROR "Qt5 Multimedia development files are not found. " "Qt5Multimedia development package is to install.") ENDIF(NOT Qt5Multimedia_FOUND) -ENDIF() IF (NOT WIN32) FIND_PACKAGE ( LibFTDI1 NO_MODULE REQUIRED ) IF(NOT LibFTDI1_FOUND) MESSAGE(FATAL_ERROR "LibFTDI1 files are not found. " - "LibFTDI1 and LibFTDIPP1 development packages are to install.") + "need to install LibFTDI1 development packages.") ENDIF(NOT LibFTDI1_FOUND) INCLUDE ( ${LIBFTDI_USE_FILE} ) ELSE() - SET ( BOOST_DIR "C:/Libraries/boost_1_77_0" ) + SET ( BOOST_DIR "C:/Libraries/boost_1_83_0" ) SET ( LIBFTDI_ROOT_DIR "C:/libftdi1-1.5_devkit_x86_x64_19July2020" ) SET ( LIBFTDI_LIBRARY "ftdi1" ) @@ -218,16 +201,11 @@ INCLUDE_DIRECTORIES(${LIBUSB_INCLUDE_DIRS}) # for this feature install debhelper or SET(PONYPROG_CPACK_PACKAGE_SHLIBDEPS ON) -IF(${USE_QT_VERSION} MATCHES "4") - INCLUDE_DIRECTORIES(${QT_INCLUDES}) - MESSAGE(STATUS "QT_INCLUDES ${QT_INCLUDES}") -ELSE() INCLUDE_DIRECTORIES(${QT_INCLUDES} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5PrintSupport_INCLUDE_DIRS} ${Qt5Multimedia_INCLUDE_DIRS}) #MESSAGE(STATUS "QT_INCLUDES ${QT_INCLUDES} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Multimedia_INCLUDE_DIRS}") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS} ${Qt5Multimedia_EXECUTABLE_COMPILE_FLAGS} ${Qt5PrintSupport_EXECUTABLE_COMPILE_FLAGS}") -ENDIF() configure_file ( "${PROJECT_SOURCE_DIR}/SrcPony/version-cmake.h.in" @@ -245,17 +223,10 @@ ADD_SUBDIRECTORY(SrcPony) INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/qhexedit2/src/ ${CMAKE_CURRENT_SOURCE_DIR}/SrcPony/ ) -IF(${USE_QT_VERSION} MATCHES "4") -# QT4_ADD_TRANSLATION(APP_TRANSLATIONS ${TRANSLATION}) - QT4_WRAP_CPP(APP_HEADERS_MOC ${HEX_HEADERS} ${PONY_HEADERS} ) - QT4_WRAP_UI(APP_FORMS_HEADERS ${PONY_FORMS} ) - QT4_ADD_RESOURCES(APP_RESOURCES_RCC ${APP_RESOURCES}) -ELSE() # QT5_ADD_TRANSLATION(APP_TRANSLATIONS ${TRANSLATION}) QT5_WRAP_CPP(APP_HEADERS_MOC ${HEX_HEADERS} ${PONY_HEADERS} ) QT5_WRAP_UI(APP_FORMS_HEADERS ${PONY_FORMS} ) QT5_ADD_RESOURCES(APP_RESOURCES_RCC ${APP_RESOURCES}) -ENDIF() MESSAGE(STATUS "PONY_RESOURCES ${APP_RESOURCES_RCC}") @@ -281,13 +252,7 @@ ELSE() ADD_DEFINITIONS(${QT_DEFINITIONS} -DQT_DEBUG) ENDIF() - -IF(${USE_QT_VERSION} MATCHES "4") - INCLUDE(${QT_USE_FILE}) - ADD_DEFINITIONS(${QT_DEFINITIONS} -DNO_QT3SUPPORT -DDISABLE_QT3SUPPORT -DQT_PROJECT) -ELSE() - ADD_DEFINITIONS(${Qt5Widgets_DEFINITIONS} ${Qt5PrintSupport_DEFINITIONS} ${Qt5Multimedia_DEFINITIONS} -DQT_PROJECT) -ENDIF() +ADD_DEFINITIONS(${Qt5Widgets_DEFINITIONS} ${Qt5PrintSupport_DEFINITIONS} ${Qt5Multimedia_DEFINITIONS} -DQT_PROJECT) IF(WIN32) ADD_DEFINITIONS(-DUNICODE -D_UNICODE) @@ -304,15 +269,11 @@ ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ) -IF(${USE_QT_VERSION} MATCHES "4") - TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${QT_LIBRARIES}) -ELSE() - TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${QT_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5Multimedia_LIBRARIES} ${Qt5PrintSupport_LIBRARIES}) - #MESSAGE(STATUS "QT LIBRARIES: ${QT_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5Multimedia_LIBRARIES} ${Qt5PrintSupport_LIBRARIES} ${Qt5Core_LIBRARIES}") -ENDIF() +TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${QT_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5Multimedia_LIBRARIES} ${Qt5PrintSupport_LIBRARIES}) +#MESSAGE(STATUS "QT LIBRARIES: ${QT_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5Multimedia_LIBRARIES} ${Qt5PrintSupport_LIBRARIES} ${Qt5Core_LIBRARIES}") #TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${LIBFTDI_LIBRARIES} ) -TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${LIBFTDIPP_LIBRARY} ${LIBFTDI_LIBRARY} ${LIBUSB_LIBRARIES}) +TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${LIBFTDI_LIBRARY} ${LIBUSB_LIBRARIES}) ADD_CUSTOM_TARGET (tags COMMAND ctags -R -f tags ${CMAKE_SOURCE_DIR}/SrcPony diff --git a/SrcPony/CMakeLists.txt b/SrcPony/CMakeLists.txt index ef23c998..054e6907 100644 --- a/SrcPony/CMakeLists.txt +++ b/SrcPony/CMakeLists.txt @@ -1,6 +1,7 @@ #CMakeLists.txt SET(PONY_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/aboutmdlg.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ftdi.cpp ${CMAKE_CURRENT_SOURCE_DIR}/usbwatcher.cpp ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Translator.cpp @@ -84,6 +85,7 @@ SET(PONY_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/aboutmdlg.cpp SET(PONY_NOMOC_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/e2app.h ${CMAKE_CURRENT_SOURCE_DIR}/e2awinfo.h + ${CMAKE_CURRENT_SOURCE_DIR}/ftdi.hpp ${CMAKE_CURRENT_SOURCE_DIR}/Translator.h ${CMAKE_CURRENT_SOURCE_DIR}/globals.h ${CMAKE_CURRENT_SOURCE_DIR}/device.h diff --git a/SrcPony/ftdi.cpp b/SrcPony/ftdi.cpp new file mode 100644 index 00000000..26a149c4 --- /dev/null +++ b/SrcPony/ftdi.cpp @@ -0,0 +1,704 @@ +/*************************************************************************** + ftdi.cpp - C++ wrapper for libftdi + ------------------- + begin : Mon Oct 13 2008 + copyright : (C) 2008-2020 by Marek Vavruša / libftdi developers + email : opensource@intra2net.com and marek@vavrusa.com + ***************************************************************************/ +/* +Copyright (C) 2008-2017 by Marek Vavruša / libftdi developers + +The software in this package is distributed under the GNU General +Public License version 2 (with a special exception described below). + +A copy of GNU General Public License (GPL) is included in this distribution, +in the file COPYING.GPL. + +As a special exception, if other files instantiate templates or use macros +or inline functions from this file, or you compile this file and link it +with other works to produce a work based on this file, this file +does not by itself cause the resulting work to be covered +by the GNU General Public License. + +However the source code for this file must still be made available +in accordance with section (3) of the GNU General Public License. + +This exception does not invalidate any other reasons why a work based +on this file might be covered by the GNU General Public License. +*/ +#include +#define _FTDI_DISABLE_DEPRECATED +#include "ftdi.hpp" +//#include "ftdi_i.h" +#include "ftdi.h" + +namespace Ftdi +{ + +class Context::Private +{ +public: + Private() + : open(false), ftdi(0), dev(0) + { + ftdi = ftdi_new(); + } + + ~Private() + { + if (open) + ftdi_usb_close(ftdi); + + ftdi_free(ftdi); + } + + bool open; + + struct ftdi_context* ftdi; + struct libusb_device* dev; + + std::string vendor; + std::string description; + std::string serial; +}; + +/*! \brief Constructor. + */ +Context::Context() + : d( new Private() ) +{ +} + +/*! \brief Destructor. + */ +Context::~Context() +{ +} + +bool Context::is_open() +{ + return d->open; +} + +int Context::open(int vendor, int product) +{ + // Open device + int ret = ftdi_usb_open(d->ftdi, vendor, product); + + if (ret < 0) + return ret; + + return get_strings_and_reopen(false,false,false); +} + +int Context::open(int vendor, int product, const std::string& description, const std::string& serial, unsigned int index) +{ + // translate empty strings to NULL + // -> do not use them to find the device (vs. require an empty string to be set in the EEPROM) + const char* c_description=NULL; + const char* c_serial=NULL; + if (!description.empty()) + c_description=description.c_str(); + if (!serial.empty()) + c_serial=serial.c_str(); + + int ret = ftdi_usb_open_desc_index(d->ftdi, vendor, product, c_description, c_serial, index); + + if (ret < 0) + return ret; + + return get_strings_and_reopen(false,!description.empty(),!serial.empty()); +} + +int Context::open(const std::string& description) +{ + int ret = ftdi_usb_open_string(d->ftdi, description.c_str()); + + if (ret < 0) + return ret; + + return get_strings_and_reopen(false,true,false); +} + +int Context::open(struct libusb_device *dev) +{ + if (dev != 0) + d->dev = dev; + + if (d->dev == 0) + return -1; + + return get_strings_and_reopen(); +} + +int Context::close() +{ + d->open = false; + d->dev = 0; + return ftdi_usb_close(d->ftdi); +} + +int Context::reset() +{ + return ftdi_usb_reset(d->ftdi); +} + +int Context::flush(int mask) +{ + int ret; + + switch (mask & (Input | Output)) { + case Input: + ret = ftdi_usb_purge_rx_buffer(d->ftdi); + break; + + case Output: + ret = ftdi_usb_purge_tx_buffer(d->ftdi); + break; + + case Input | Output: + ret = ftdi_usb_purge_buffers(d->ftdi); + break; + + default: + // Emulate behavior of previous version. + ret = 1; + break; + } + + return ret; +} + +int Context::tcflush(int mask) +{ + int ret; + + switch (mask & (Input | Output)) { + case Input: + ret = ftdi_tciflush(d->ftdi); + break; + + case Output: + ret = ftdi_tcoflush(d->ftdi); + break; + + case Input | Output: + ret = ftdi_tcioflush(d->ftdi); + break; + + default: + // Emulate behavior of previous version. + ret = 1; + break; + } + + return ret; +} + +int Context::set_interface(enum ftdi_interface interface) +{ + return ftdi_set_interface(d->ftdi, interface); +} + +void Context::set_usb_device(struct libusb_device_handle *dev) +{ + ftdi_set_usbdev(d->ftdi, dev); + d->dev = libusb_get_device(dev); +} + +int Context::set_baud_rate(int baudrate) +{ + return ftdi_set_baudrate(d->ftdi, baudrate); +} + +int Context::set_line_property(enum ftdi_bits_type bits, enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity) +{ + return ftdi_set_line_property(d->ftdi, bits, sbit, parity); +} + +int Context::set_line_property(enum ftdi_bits_type bits, enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity, enum ftdi_break_type break_type) +{ + return ftdi_set_line_property2(d->ftdi, bits, sbit, parity, break_type); +} + +int Context::get_usb_read_timeout() const +{ + return d->ftdi->usb_read_timeout; +} + +void Context::set_usb_read_timeout(int usb_read_timeout) +{ + d->ftdi->usb_read_timeout = usb_read_timeout; +} + +int Context::get_usb_write_timeout() const +{ + return d->ftdi->usb_write_timeout; +} + +void Context::set_usb_write_timeout(int usb_write_timeout) +{ + d->ftdi->usb_write_timeout = usb_write_timeout; +} + +int Context::read(unsigned char *buf, int size) +{ + return ftdi_read_data(d->ftdi, buf, size); +} + +int Context::set_read_chunk_size(unsigned int chunksize) +{ + return ftdi_read_data_set_chunksize(d->ftdi, chunksize); +} + +int Context::read_chunk_size() +{ + unsigned chunk = -1; + if (ftdi_read_data_get_chunksize(d->ftdi, &chunk) < 0) + return -1; + + return chunk; +} + +int Context::write(const unsigned char *buf, int size) +{ + return ftdi_write_data(d->ftdi, buf, size); +} + +int Context::set_write_chunk_size(unsigned int chunksize) +{ + return ftdi_write_data_set_chunksize(d->ftdi, chunksize); +} + +int Context::write_chunk_size() +{ + unsigned chunk = -1; + if (ftdi_write_data_get_chunksize(d->ftdi, &chunk) < 0) + return -1; + + return chunk; +} + +int Context::set_flow_control(int flowctrl) +{ + return ftdi_setflowctrl(d->ftdi, flowctrl); +} + +int Context::set_modem_control(int mask) +{ + int dtr = 0, rts = 0; + + if (mask & Dtr) + dtr = 1; + if (mask & Rts) + rts = 1; + + return ftdi_setdtr_rts(d->ftdi, dtr, rts); +} + +int Context::set_dtr(bool state) +{ + return ftdi_setdtr(d->ftdi, state); +} + +int Context::set_rts(bool state) +{ + return ftdi_setrts(d->ftdi, state); +} + +int Context::set_latency(unsigned char latency) +{ + return ftdi_set_latency_timer(d->ftdi, latency); +} + +unsigned Context::latency() +{ + unsigned char latency = 0; + ftdi_get_latency_timer(d->ftdi, &latency); + return latency; +} + +unsigned short Context::poll_modem_status() +{ + unsigned short status = 0; + ftdi_poll_modem_status(d->ftdi, &status); + return status; +} + +int Context::set_event_char(unsigned char eventch, unsigned char enable) +{ + return ftdi_set_event_char(d->ftdi, eventch, enable); +} + +int Context::set_error_char(unsigned char errorch, unsigned char enable) +{ + return ftdi_set_error_char(d->ftdi, errorch, enable); +} + +int Context::set_bitmode(unsigned char bitmask, unsigned char mode) +{ + return ftdi_set_bitmode(d->ftdi, bitmask, mode); +} + +int Context::set_bitmode(unsigned char bitmask, enum ftdi_mpsse_mode mode) +{ + return ftdi_set_bitmode(d->ftdi, bitmask, mode); +} + +int Context::bitbang_disable() +{ + return ftdi_disable_bitbang(d->ftdi); +} + +int Context::read_pins(unsigned char *pins) +{ + return ftdi_read_pins(d->ftdi, pins); +} + +const char* Context::error_string() +{ + return ftdi_get_error_string(d->ftdi); +} + +int Context::get_strings(bool vendor, bool description, bool serial) +{ + // Prepare buffers + char ivendor[512], idesc[512], iserial[512]; + + int ret = ftdi_usb_get_strings(d->ftdi, d->dev, vendor?ivendor:NULL, 512, description?idesc:NULL, 512, serial?iserial:NULL, 512); + + if (ret < 0) + return -1; + + d->vendor = ivendor; + d->description = idesc; + d->serial = iserial; + + return 1; +} + +int Context::get_strings_and_reopen(bool vendor, bool description, bool serial) +{ + int ret = 0; + + if(vendor || description || serial) + { + if (d->dev == 0) + { + d->dev = libusb_get_device(d->ftdi->usb_dev); + } + + // Get device strings (closes device) + ret=get_strings(vendor, description, serial); + if (ret < 0) + { + d->open = 0; + return ret; + } + + // Reattach device + ret = ftdi_usb_open_dev(d->ftdi, d->dev); + d->open = (ret >= 0); + } + + return ret; +} + +/*! \brief Device strings properties. + */ +const std::string& Context::vendor() +{ + if(d->vendor.empty()) + get_strings_and_reopen(true,false,false); + return d->vendor; +} + +/*! \brief Device strings properties. + */ +const std::string& Context::description() +{ + if(d->description.empty()) + get_strings_and_reopen(false,true,false); + return d->description; +} + +/*! \brief Device strings properties. + */ +const std::string& Context::serial() +{ + if(d->serial.empty()) + get_strings_and_reopen(false,false,true); + return d->serial; +} + +void Context::set_context(struct ftdi_context* context) +{ + ftdi_free(d->ftdi); + d->ftdi = context; +} + +void Context::set_usb_device(struct libusb_device *dev) +{ + d->dev = dev; +} + +struct ftdi_context* Context::context() +{ + return d->ftdi; +} + +/** +class Eeprom::Private +{ +public: + Private() + : context(0) + {} + + struct ftdi_eeprom eeprom; + struct ftdi_context* context; +}; + +Eeprom::Eeprom(Context* parent) + : d ( new Private() ) +{ + d->context = parent->context(); +} + +Eeprom::~Eeprom() +{ +} + +int Eeprom::init_defaults(char* manufacturer, char *product, char * serial) +{ + return ftdi_eeprom_initdefaults(d->context, manufacturer, product, serial); +} + +int Eeprom::chip_id(unsigned int *chipid) +{ + return ftdi_read_chipid(d->context, chipid); +} + +int Eeprom::build(unsigned char *output) +{ + return ftdi_eeprom_build(d->context); +} + +int Eeprom::read(unsigned char *eeprom) +{ + return ftdi_read_eeprom(d->context); +} + +int Eeprom::write(unsigned char *eeprom) +{ + return ftdi_write_eeprom(d->context); +} + +int Eeprom::read_location(int eeprom_addr, unsigned short *eeprom_val) +{ + return ftdi_read_eeprom_location(d->context, eeprom_addr, eeprom_val); +} + +int Eeprom::write_location(int eeprom_addr, unsigned short eeprom_val) +{ + return ftdi_write_eeprom_location(d->context, eeprom_addr, eeprom_val); +} + +int Eeprom::erase() +{ + return ftdi_erase_eeprom(d->context); +} +**/ + +class List::Private +{ +public: + Private(struct ftdi_device_list* _devlist) + : devlist(_devlist) + {} + + ~Private() + { + if(devlist) + ftdi_list_free(&devlist); + } + + std::list list; + struct ftdi_device_list* devlist; +}; + +List::List(struct ftdi_device_list* devlist) + : d( new Private(devlist) ) +{ + if (devlist != 0) + { + // Iterate list + for (; devlist != 0; devlist = devlist->next) + { + Context c; + c.set_usb_device(devlist->dev); + c.get_strings(); + d->list.push_back(c); + } + } +} + +List::~List() +{ +} + +/** +* Return begin iterator for accessing the contained list elements +* @return Iterator +*/ +List::iterator List::begin() +{ + return d->list.begin(); +} + +/** +* Return end iterator for accessing the contained list elements +* @return Iterator +*/ +List::iterator List::end() +{ + return d->list.end(); +} + +/** +* Return begin iterator for accessing the contained list elements +* @return Const iterator +*/ +List::const_iterator List::begin() const +{ + return d->list.begin(); +} + +/** +* Return end iterator for accessing the contained list elements +* @return Const iterator +*/ +List::const_iterator List::end() const +{ + return d->list.end(); +} + +/** +* Return begin reverse iterator for accessing the contained list elements +* @return Reverse iterator +*/ +List::reverse_iterator List::rbegin() +{ + return d->list.rbegin(); +} + +/** +* Return end reverse iterator for accessing the contained list elements +* @return Reverse iterator +*/ +List::reverse_iterator List::rend() +{ + return d->list.rend(); +} + +/** +* Return begin reverse iterator for accessing the contained list elements +* @return Const reverse iterator +*/ +List::const_reverse_iterator List::rbegin() const +{ + return d->list.rbegin(); +} + +/** +* Return end reverse iterator for accessing the contained list elements +* @return Const reverse iterator +*/ +List::const_reverse_iterator List::rend() const +{ + return d->list.rend(); + +} + +/** +* Get number of elements stored in the list +* @return Number of elements +*/ +List::ListType::size_type List::size() const +{ + return d->list.size(); +} + +/** +* Check if list is empty +* @return True if empty, false otherwise +*/ +bool List::empty() const +{ + return d->list.empty(); +} + +/** + * Removes all elements. Invalidates all iterators. + * Do it in a non-throwing way and also make + * sure we really free the allocated memory. + */ +void List::clear() +{ + ListType().swap(d->list); + + // Free device list + if (d->devlist) + { + ftdi_list_free(&d->devlist); + d->devlist = 0; + } +} + +/** + * Appends a copy of the element as the new last element. + * @param element Value to copy and append +*/ +void List::push_back(const Context& element) +{ + d->list.push_back(element); +} + +/** + * Adds a copy of the element as the new first element. + * @param element Value to copy and add +*/ +void List::push_front(const Context& element) +{ + d->list.push_front(element); +} + +/** + * Erase one element pointed by iterator + * @param pos Element to erase + * @return Position of the following element (or end()) +*/ +List::iterator List::erase(iterator pos) +{ + return d->list.erase(pos); +} + +/** + * Erase a range of elements + * @param beg Begin of range + * @param end End of range + * @return Position of the element after the erased range (or end()) +*/ +List::iterator List::erase(iterator beg, iterator end) +{ + return d->list.erase(beg, end); +} + +List* List::find_all(Context &context, int vendor, int product) +{ + struct ftdi_device_list* dlist = 0; + ftdi_usb_find_all(context.context(), &dlist, vendor, product); + return new List(dlist); +} + +} diff --git a/SrcPony/ftdi.hpp b/SrcPony/ftdi.hpp new file mode 100644 index 00000000..24583273 --- /dev/null +++ b/SrcPony/ftdi.hpp @@ -0,0 +1,222 @@ +/*************************************************************************** + ftdi.hpp - C++ wrapper for libftdi + ------------------- + begin : Mon Oct 13 2008 + copyright : (C) 2008-2020 by Marek Vavruša and libftdi developers + email : opensource@intra2net.com and marek@vavrusa.com + ***************************************************************************/ +/* +Copyright (C) 2008-2017 by Marek Vavruša and libftdi developers + +The software in this package is distributed under the GNU General +Public License version 2 (with a special exception described below). + +A copy of GNU General Public License (GPL) is included in this distribution, +in the file COPYING.GPL. + +As a special exception, if other files instantiate templates or use macros +or inline functions from this file, or you compile this file and link it +with other works to produce a work based on this file, this file +does not by itself cause the resulting work to be covered +by the GNU General Public License. + +However the source code for this file must still be made available +in accordance with section (3) of the GNU General Public License. + +This exception does not invalidate any other reasons why a work based +on this file might be covered by the GNU General Public License. +*/ +#ifndef __libftdi_hpp__ +#define __libftdi_hpp__ + +#include +#include +#include +#include + +namespace Ftdi +{ + +/* Forward declarations*/ +class List; +class Eeprom; + +/*! \brief FTDI device context. + * Represents single FTDI device context. + */ +class Context +{ + /* Friends */ + friend class Eeprom; + friend class List; + +public: + /*! \brief Direction flags for flush(). + */ + enum Direction + { + Input = 0x2, + Output = 0x1, + }; + + /*! \brief Modem control flags. + */ + enum ModemCtl + { + Dtr = 0x2, + Rts = 0x1, + }; + + /* Constructor, Destructor */ + Context(); + ~Context(); + + /* Properties */ + Eeprom* eeprom(); + const std::string& vendor(); + const std::string& description(); + const std::string& serial(); + + /* Device manipulators */ + bool is_open(); + int open(struct libusb_device *dev = 0); + int open(int vendor, int product); + int open(int vendor, int product, const std::string& description, const std::string& serial = std::string(), unsigned int index=0); + int open(const std::string& description); + int close(); + int reset(); + int DEPRECATED(flush)(int mask = Input|Output); + int tcflush(int mask = Input|Output); + int set_interface(enum ftdi_interface interface); + void set_usb_device(struct libusb_device_handle *dev); + + /* Line manipulators */ + int set_baud_rate(int baudrate); + int set_line_property(enum ftdi_bits_type bits, enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity); + int set_line_property(enum ftdi_bits_type bits, enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity, enum ftdi_break_type break_type); + int get_usb_read_timeout() const; + void set_usb_read_timeout(int usb_read_timeout); + int get_usb_write_timeout() const; + void set_usb_write_timeout(int usb_write_timeout); + + /* I/O */ + int read(unsigned char *buf, int size); + int write(const unsigned char *buf, int size); + int set_read_chunk_size(unsigned int chunksize); + int set_write_chunk_size(unsigned int chunksize); + int read_chunk_size(); + int write_chunk_size(); + + /* Async IO + TODO: should wrap? + int writeAsync(const unsigned char *buf, int size); + void asyncComplete(int wait_for_more); + */ + + /* Flow control */ + int set_event_char(unsigned char eventch, unsigned char enable); + int set_error_char(unsigned char errorch, unsigned char enable); + int set_flow_control(int flowctrl); + int set_modem_control(int mask = Dtr|Rts); + int set_latency(unsigned char latency); + int set_dtr(bool state); + int set_rts(bool state); + + unsigned short poll_modem_status(); + unsigned latency(); + + /* BitBang mode */ + int set_bitmode(unsigned char bitmask, unsigned char mode); + int set_bitmode(unsigned char bitmask, enum ftdi_mpsse_mode mode); + int bitbang_disable(); + int read_pins(unsigned char *pins); + + /* Misc */ + const char* error_string(); + +protected: + int get_strings(bool vendor=true, bool description=true, bool serial=true); + int get_strings_and_reopen(bool vendor=true, bool description=true, bool serial=true); + + /* Properties */ + struct ftdi_context* context(); + void set_context(struct ftdi_context* context); + void set_usb_device(struct libusb_device *dev); + +private: + class Private; + std::shared_ptr d; +}; + +/*! \brief Device EEPROM. + */ +class Eeprom +{ +public: + Eeprom(Context* parent); + ~Eeprom(); + + int init_defaults(char *manufacturer, char* product, char * serial); + int chip_id(unsigned int *chipid); + int build(unsigned char *output); + + int read(unsigned char *eeprom); + int write(unsigned char *eeprom); + int read_location(int eeprom_addr, unsigned short *eeprom_val); + int write_location(int eeprom_addr, unsigned short eeprom_val); + int erase(); + +private: + class Private; + std::shared_ptr d; +}; + +/*! \brief Device list. + */ +class List +{ +public: + List(struct ftdi_device_list* devlist = 0); + ~List(); + + static List* find_all(Context &context, int vendor, int product); + + /// List type storing "Context" objects + typedef std::list ListType; + /// Iterator type for the container + typedef ListType::iterator iterator; + /// Const iterator type for the container + typedef ListType::const_iterator const_iterator; + /// Reverse iterator type for the container + typedef ListType::reverse_iterator reverse_iterator; + /// Const reverse iterator type for the container + typedef ListType::const_reverse_iterator const_reverse_iterator; + + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + + reverse_iterator rbegin(); + reverse_iterator rend(); + const_reverse_iterator rbegin() const; + const_reverse_iterator rend() const; + + ListType::size_type size() const; + bool empty() const; + void clear(); + + void push_back(const Context& element); + void push_front(const Context& element); + + iterator erase(iterator pos); + iterator erase(iterator beg, iterator end); + +private: + class Private; + std::shared_ptr d; +}; + +} + +#endif diff --git a/ponyprog.pro b/ponyprog.pro index 3784a626..c5fe818e 100644 --- a/ponyprog.pro +++ b/ponyprog.pro @@ -189,13 +189,14 @@ SOURCES += SrcPony/aboutmdlg.cpp \ SrcPony/Translator.cpp \ SrcPony/usbwatcher.cpp \ SrcPony/prefdialog.cpp \ + SrcPony/ftdi.cpp \ qhexedit2/src/chunks.cpp \ qhexedit2/src/commands.cpp \ qhexedit2/src/qhexedit.cpp -HEADERS += SrcPony/e2app.h \ +HEADERS += SrcPony/e2app.h \ SrcPony/e2awinfo.h \ - SrcPony/e2cmdw.h \ + SrcPony/e2cmdw.h \ SrcPony/globals.h \ SrcPony/device.h \ SrcPony/microbus.h \ @@ -273,6 +274,7 @@ HEADERS += SrcPony/e2app.h \ SrcPony/interfconv.h \ SrcPony/usbwatcher.h \ SrcPony/prefdialog.h \ + SrcPony/ftdi.hpp \ qhexedit2/src/chunks.h \ qhexedit2/src/commands.h \ qhexedit2/src/qhexedit.h @@ -303,14 +305,14 @@ FORMS += SrcPony/forms/aboutdlg.ui \ unix:!macx: LIBS += -L/usr/local/lib #libftdi -unix:!macx: QMAKE_CXXFLAGS += $$system(pkg-config libftdipp1 --cflags) -unix:!macx: LIBS += $$system(pkg-config libftdipp1 --libs) +unix:!macx: QMAKE_CXXFLAGS += $$system(pkg-config libftdi1 --cflags) +unix:!macx: LIBS += $$system(pkg-config libftdi1 --libs) win32 { isEmpty(FTDIPATH): FTDIPATH = c:/libftdi1-1.5_devkit_x86_x64_19July2020 !isEmpty(BOOSTPATH): QMAKE_CXXFLAGS += -I $$BOOSTPATH QMAKE_CXXFLAGS += -I $$FTDIPATH/include/libftdi -I $$FTDIPATH/include/libusb-1.0 -I $$FTDIPATH/include - LIBS += -L $$FTDIPATH/lib32 -lftdipp1 -lftdi1 -lusb-1.0 + LIBS += -L $$FTDIPATH/lib32 -lftdi1 -lusb-1.0 } # # Make sure QM translations are generated.