From 7a4720ed0229ae93e9d48bf3a9e6d5a1af2879ad Mon Sep 17 00:00:00 2001 From: trabus322 Date: Mon, 8 Apr 2024 21:41:26 +0200 Subject: [PATCH] p a i n --- CMakeLists.txt | 4 + build/CMakeCache.txt | 397 ++++ .../3.28.3/CompilerIdC/CMakeCCompilerId.c | 880 +++++++ .../CompilerIdCXX/CMakeCXXCompilerId.cpp | 869 +++++++ build/CMakeFiles/TargetDirectories.txt | 11 + build/src/hoymilesSunspecInterface_exec | Bin 0 -> 1159272 bytes build/src/libmodbus/config.h | 291 +++ build/src/libmodbus/inc/config.h | 291 +++ src/CMakeLists.txt | 9 + src/hoymiles/CMakeLists.txt | 8 + src/hoymiles/inc/dtu.h | 39 + src/hoymiles/inc/microinverter.h | 48 + src/hoymiles/inc/port.h | 49 + .../inc/portParameters/portParameters.h | 94 + .../portParameters/portParametersGeneric.h | 77 + src/hoymiles/inc/sunspec.h | 37 + .../inc/sunspecParameters/sunspecParameters.h | 15 + .../sunspecParametersGeneric.h | 124 + src/hoymiles/src/dtu.cpp | 152 ++ src/hoymiles/src/microinverter.cpp | 139 ++ src/hoymiles/src/port.cpp | 223 ++ .../src/portParameters/portParameters.cpp | 51 + .../portParameters/portParametersGeneric.cpp | 83 + src/hoymiles/src/sunspec.cpp | 34 + .../sunspecParameters/sunspecParameters.cpp | 23 + .../sunspecParametersGeneric.cpp | 17 + src/libmodbus/CMakeLists.txt | 7 + src/libmodbus/config.h.in | 291 +++ src/libmodbus/inc/config.h | 291 +++ src/libmodbus/inc/modbus-private.h | 121 + src/libmodbus/inc/modbus-rtu-private.h | 77 + src/libmodbus/inc/modbus-rtu.h | 43 + src/libmodbus/inc/modbus-tcp-private.h | 41 + src/libmodbus/inc/modbus-tcp.h | 52 + src/libmodbus/inc/modbus-version.h | 51 + src/libmodbus/inc/modbus.h | 329 +++ src/libmodbus/src/modbus-data.c | 292 +++ src/libmodbus/src/modbus-rtu.c | 1290 ++++++++++ src/libmodbus/src/modbus-tcp.c | 974 ++++++++ src/libmodbus/src/modbus.c | 2071 +++++++++++++++++ src/main.cpp | 11 + 41 files changed, 9906 insertions(+) create mode 100644 build/CMakeCache.txt create mode 100644 build/CMakeFiles/3.28.3/CompilerIdC/CMakeCCompilerId.c create mode 100644 build/CMakeFiles/3.28.3/CompilerIdCXX/CMakeCXXCompilerId.cpp create mode 100644 build/CMakeFiles/TargetDirectories.txt create mode 100755 build/src/hoymilesSunspecInterface_exec create mode 100644 build/src/libmodbus/config.h create mode 100644 build/src/libmodbus/inc/config.h create mode 100644 src/CMakeLists.txt create mode 100644 src/hoymiles/CMakeLists.txt create mode 100644 src/hoymiles/inc/dtu.h create mode 100644 src/hoymiles/inc/microinverter.h create mode 100644 src/hoymiles/inc/port.h create mode 100644 src/hoymiles/inc/portParameters/portParameters.h create mode 100644 src/hoymiles/inc/portParameters/portParametersGeneric.h create mode 100644 src/hoymiles/inc/sunspec.h create mode 100644 src/hoymiles/inc/sunspecParameters/sunspecParameters.h create mode 100644 src/hoymiles/inc/sunspecParameters/sunspecParametersGeneric.h create mode 100644 src/hoymiles/src/dtu.cpp create mode 100644 src/hoymiles/src/microinverter.cpp create mode 100644 src/hoymiles/src/port.cpp create mode 100644 src/hoymiles/src/portParameters/portParameters.cpp create mode 100644 src/hoymiles/src/portParameters/portParametersGeneric.cpp create mode 100644 src/hoymiles/src/sunspec.cpp create mode 100644 src/hoymiles/src/sunspecParameters/sunspecParameters.cpp create mode 100644 src/hoymiles/src/sunspecParameters/sunspecParametersGeneric.cpp create mode 100644 src/libmodbus/CMakeLists.txt create mode 100644 src/libmodbus/config.h.in create mode 100644 src/libmodbus/inc/config.h create mode 100644 src/libmodbus/inc/modbus-private.h create mode 100644 src/libmodbus/inc/modbus-rtu-private.h create mode 100644 src/libmodbus/inc/modbus-rtu.h create mode 100644 src/libmodbus/inc/modbus-tcp-private.h create mode 100644 src/libmodbus/inc/modbus-tcp.h create mode 100644 src/libmodbus/inc/modbus-version.h create mode 100644 src/libmodbus/inc/modbus.h create mode 100644 src/libmodbus/src/modbus-data.c create mode 100644 src/libmodbus/src/modbus-rtu.c create mode 100644 src/libmodbus/src/modbus-tcp.c create mode 100644 src/libmodbus/src/modbus.c create mode 100644 src/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e69de29..3bdc78d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.6.0) +project(hoymilesSunspecInterface VERSION 0.1.0 LANGUAGES C CXX) + +add_subdirectory(src) \ No newline at end of file diff --git a/build/CMakeCache.txt b/build/CMakeCache.txt new file mode 100644 index 0000000..0c31c25 --- /dev/null +++ b/build/CMakeCache.txt @@ -0,0 +1,397 @@ +# This is the CMakeCache file. +# For build in directory: /home/trabus322/workspace/code/hoymilesSunspecInterface/build +# It was generated by CMake: /usr/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//Path to a program. +CMAKE_ADDR2LINE:FILEPATH=/usr/bin/llvm-addr2line + +//Path to a program. +CMAKE_AR:FILEPATH=/usr/bin/llvm-ar + +//No help, variable specified on the command line. +CMAKE_BUILD_TYPE:STRING=Debug + +//No help, variable specified on the command line. +CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/clang++ + +//LLVM archiver +CMAKE_CXX_COMPILER_AR:FILEPATH=/usr/bin/llvm-ar + +//`clang-scan-deps` dependency scanner +CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS:FILEPATH=/usr/bin/clang-scan-deps + +//Generate index for LLVM archive +CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/usr/bin/llvm-ranlib + +//Flags used by the CXX compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the CXX compiler during DEBUG builds. +CMAKE_CXX_FLAGS_DEBUG:STRING=-g + +//Flags used by the CXX compiler during MINSIZEREL builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the CXX compiler during RELEASE builds. +CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the CXX compiler during RELWITHDEBINFO builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//No help, variable specified on the command line. +CMAKE_C_COMPILER:FILEPATH=/usr/bin/clang + +//LLVM archiver +CMAKE_C_COMPILER_AR:FILEPATH=/usr/bin/llvm-ar + +//`clang-scan-deps` dependency scanner +CMAKE_C_COMPILER_CLANG_SCAN_DEPS:FILEPATH=/usr/bin/clang-scan-deps + +//Generate index for LLVM archive +CMAKE_C_COMPILER_RANLIB:FILEPATH=/usr/bin/llvm-ranlib + +//Flags used by the C compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the C compiler during DEBUG builds. +CMAKE_C_FLAGS_DEBUG:STRING=-g + +//Flags used by the C compiler during MINSIZEREL builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the C compiler during RELEASE builds. +CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the C compiler during RELWITHDEBINFO builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Path to a program. +CMAKE_DLLTOOL:FILEPATH=/usr/bin/llvm-dlltool + +//Flags used by the linker during all build types. +CMAKE_EXE_LINKER_FLAGS:STRING= + +//Flags used by the linker during DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during MINSIZEREL builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during RELEASE builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during RELWITHDEBINFO builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//No help, variable specified on the command line. +CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE + +//Value Computed by CMake. +CMAKE_FIND_PACKAGE_REDIRECTS_DIR:STATIC=/home/trabus322/workspace/code/hoymilesSunspecInterface/build/CMakeFiles/pkgRedirects + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//Path to a program. +CMAKE_LINKER:FILEPATH=/usr/bin/ld + +//Program used to build from build.ninja files. +CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/ninja + +//Flags used by the linker during the creation of modules during +// all build types. +CMAKE_MODULE_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of modules during +// DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of modules during +// MINSIZEREL builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of modules during +// RELEASE builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of modules during +// RELWITHDEBINFO builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/usr/bin/llvm-nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/usr/bin/llvm-objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/usr/bin/llvm-objdump + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=hoymilesSunspecInterface + +//Value Computed by CMake +CMAKE_PROJECT_VERSION:STATIC=0.1.0 + +//Value Computed by CMake +CMAKE_PROJECT_VERSION_MAJOR:STATIC=0 + +//Value Computed by CMake +CMAKE_PROJECT_VERSION_MINOR:STATIC=1 + +//Value Computed by CMake +CMAKE_PROJECT_VERSION_PATCH:STATIC=0 + +//Value Computed by CMake +CMAKE_PROJECT_VERSION_TWEAK:STATIC= + +//Path to a program. +CMAKE_RANLIB:FILEPATH=/usr/bin/llvm-ranlib + +//Path to a program. +CMAKE_READELF:FILEPATH=/usr/bin/llvm-readelf + +//Flags used by the linker during the creation of shared libraries +// during all build types. +CMAKE_SHARED_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of shared libraries +// during DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of shared libraries +// during MINSIZEREL builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELEASE builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELWITHDEBINFO builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries +// during all build types. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of static libraries +// during DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during MINSIZEREL builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELEASE builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELWITHDEBINFO builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_STRIP:FILEPATH=/usr/bin/llvm-strip + +//Path to a program. +CMAKE_TAPI:FILEPATH=CMAKE_TAPI-NOTFOUND + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//Value Computed by CMake +hoymilesSunspecInterface_BINARY_DIR:STATIC=/home/trabus322/workspace/code/hoymilesSunspecInterface/build + +//Value Computed by CMake +hoymilesSunspecInterface_IS_TOP_LEVEL:STATIC=ON + +//Value Computed by CMake +hoymilesSunspecInterface_SOURCE_DIR:STATIC=/home/trabus322/workspace/code/hoymilesSunspecInterface + +//Dependencies for the target +libhoymiles_LIB_DEPENDS:STATIC=general;libmodbus; + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_ADDR2LINE +CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/home/trabus322/workspace/code/hoymilesSunspecInterface/build +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=28 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=3 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/usr/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest +//ADVANCED property for variable: CMAKE_CXX_COMPILER +CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR +CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS +CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB +CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER +CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_AR +CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_CLANG_SCAN_DEPS +CMAKE_C_COMPILER_CLANG_SCAN_DEPS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB +CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_DLLTOOL +CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 +//Path to cache edit program executable. +CMAKE_EDIT_COMMAND:INTERNAL=/usr/bin/ccmake +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Ninja +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL= +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/home/trabus322/workspace/code/hoymilesSunspecInterface +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=0 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MAKE_PROGRAM +CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=4 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_READELF +CMAKE_READELF-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/usr/share/cmake +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_TAPI +CMAKE_TAPI-ADVANCED:INTERNAL=1 +//uname command +CMAKE_UNAME:INTERNAL=/usr/bin/uname +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 +//linker supports push/pop state +_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED:INTERNAL=TRUE + diff --git a/build/CMakeFiles/3.28.3/CompilerIdC/CMakeCCompilerId.c b/build/CMakeFiles/3.28.3/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 0000000..0a0ec9b --- /dev/null +++ b/build/CMakeFiles/3.28.3/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,880 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif +#if defined(__CLASSIC_C__) +/* cv-qualifiers did not exist in K&R C */ +# define const +# define volatile +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__open_xl__) && defined(__clang__) +# define COMPILER_ID "IBMClang" +# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__) +# define COMPILER_VERSION_MINOR DEC(__open_xl_release__) +# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__) + + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(__clang__) && defined(__cray__) +# define COMPILER_ID "CrayClang" +# define COMPILER_VERSION_MAJOR DEC(__cray_major__) +# define COMPILER_VERSION_MINOR DEC(__cray_minor__) +# define COMPILER_VERSION_PATCH DEC(__cray_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TASKING__) +# define COMPILER_ID "Tasking" + # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000) + # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100) +# define COMPILER_VERSION_INTERNAL DEC(__VERSION__) + +#elif defined(__ORANGEC__) +# define COMPILER_ID "OrangeC" +# define COMPILER_VERSION_MAJOR DEC(__ORANGEC_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__ORANGEC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__ORANGEC_PATCHLEVEL__) + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION/100 % 100) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) +# define COMPILER_ID "LCC" +# define COMPILER_VERSION_MAJOR DEC(__LCC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__LCC__ % 100) +# if defined(__LCC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) +# endif +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define SIMULATE_ID "GNU" +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(_ADI_COMPILER) +# define COMPILER_ID "ADSP" +#if defined(__VERSIONNUM__) + /* __VERSIONNUM__ = 0xVVRRPPTT */ +# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF) +# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF) +# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF) +# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if !defined(__STDC__) && !defined(__clang__) +# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) +# define C_VERSION "90" +# else +# define C_VERSION +# endif +#elif __STDC_VERSION__ > 201710L +# define C_VERSION "23" +#elif __STDC_VERSION__ >= 201710L +# define C_VERSION "17" +#elif __STDC_VERSION__ >= 201000L +# define C_VERSION "11" +#elif __STDC_VERSION__ >= 199901L +# define C_VERSION "99" +#else +# define C_VERSION "90" +#endif +const char* info_language_standard_default = + "INFO" ":" "standard_default[" C_VERSION "]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/build/CMakeFiles/3.28.3/CompilerIdCXX/CMakeCXXCompilerId.cpp b/build/CMakeFiles/3.28.3/CompilerIdCXX/CMakeCXXCompilerId.cpp new file mode 100644 index 0000000..9c9c90e --- /dev/null +++ b/build/CMakeFiles/3.28.3/CompilerIdCXX/CMakeCXXCompilerId.cpp @@ -0,0 +1,869 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__COMO__) +# define COMPILER_ID "Comeau" + /* __COMO_VERSION__ = VRR */ +# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) +# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) + +#elif defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__open_xl__) && defined(__clang__) +# define COMPILER_ID "IBMClang" +# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__) +# define COMPILER_VERSION_MINOR DEC(__open_xl_release__) +# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__) + + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(__clang__) && defined(__cray__) +# define COMPILER_ID "CrayClang" +# define COMPILER_VERSION_MAJOR DEC(__cray_major__) +# define COMPILER_VERSION_MINOR DEC(__cray_minor__) +# define COMPILER_VERSION_PATCH DEC(__cray_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TASKING__) +# define COMPILER_ID "Tasking" + # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000) + # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100) +# define COMPILER_VERSION_INTERNAL DEC(__VERSION__) + +#elif defined(__ORANGEC__) +# define COMPILER_ID "OrangeC" +# define COMPILER_VERSION_MAJOR DEC(__ORANGEC_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__ORANGEC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__ORANGEC_PATCHLEVEL__) + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION/100 % 100) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) +# define COMPILER_ID "LCC" +# define COMPILER_VERSION_MAJOR DEC(__LCC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__LCC__ % 100) +# if defined(__LCC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) +# endif +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define SIMULATE_ID "GNU" +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif +# endif + +#elif defined(__GNUC__) || defined(__GNUG__) +# define COMPILER_ID "GNU" +# if defined(__GNUC__) +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# else +# define COMPILER_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(_ADI_COMPILER) +# define COMPILER_ID "ADSP" +#if defined(__VERSIONNUM__) + /* __VERSIONNUM__ = 0xVVRRPPTT */ +# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF) +# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF) +# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF) +# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L +# if defined(__INTEL_CXX11_MODE__) +# if defined(__cpp_aggregate_nsdmi) +# define CXX_STD 201402L +# else +# define CXX_STD 201103L +# endif +# else +# define CXX_STD 199711L +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) +# define CXX_STD _MSVC_LANG +#else +# define CXX_STD __cplusplus +#endif + +const char* info_language_standard_default = "INFO" ":" "standard_default[" +#if CXX_STD > 202002L + "23" +#elif CXX_STD > 201703L + "20" +#elif CXX_STD >= 201703L + "17" +#elif CXX_STD >= 201402L + "14" +#elif CXX_STD >= 201103L + "11" +#else + "98" +#endif +"]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} diff --git a/build/CMakeFiles/TargetDirectories.txt b/build/CMakeFiles/TargetDirectories.txt new file mode 100644 index 0000000..a2960e1 --- /dev/null +++ b/build/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,11 @@ +/home/trabus322/workspace/code/hoymilesSunspecInterface/build/CMakeFiles/edit_cache.dir +/home/trabus322/workspace/code/hoymilesSunspecInterface/build/CMakeFiles/rebuild_cache.dir +/home/trabus322/workspace/code/hoymilesSunspecInterface/build/src/CMakeFiles/hoymilesSunspecInterface_exec.dir +/home/trabus322/workspace/code/hoymilesSunspecInterface/build/src/CMakeFiles/edit_cache.dir +/home/trabus322/workspace/code/hoymilesSunspecInterface/build/src/CMakeFiles/rebuild_cache.dir +/home/trabus322/workspace/code/hoymilesSunspecInterface/build/src/libmodbus/CMakeFiles/libmodbus.dir +/home/trabus322/workspace/code/hoymilesSunspecInterface/build/src/libmodbus/CMakeFiles/edit_cache.dir +/home/trabus322/workspace/code/hoymilesSunspecInterface/build/src/libmodbus/CMakeFiles/rebuild_cache.dir +/home/trabus322/workspace/code/hoymilesSunspecInterface/build/src/hoymiles/CMakeFiles/libhoymiles.dir +/home/trabus322/workspace/code/hoymilesSunspecInterface/build/src/hoymiles/CMakeFiles/edit_cache.dir +/home/trabus322/workspace/code/hoymilesSunspecInterface/build/src/hoymiles/CMakeFiles/rebuild_cache.dir diff --git a/build/src/hoymilesSunspecInterface_exec b/build/src/hoymilesSunspecInterface_exec new file mode 100755 index 0000000000000000000000000000000000000000..9c003c636b42c47292cb6aeeedcbceba19d9da28 GIT binary patch literal 1159272 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
    &wu-vcX(M&I!X28?H}a31 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%0DMoY#>szLVn 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%0A0wOEJsjJ$#3Hd0(P#ciUv%@nuA6t|s$J1A}! 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 K)d2P5;C}&S9(>;b literal 0 HcmV?d00001 diff --git a/build/src/libmodbus/config.h b/build/src/libmodbus/config.h new file mode 100644 index 0000000..91492e8 --- /dev/null +++ b/build/src/libmodbus/config.h @@ -0,0 +1,291 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the `accept4' function. */ +#undef HAVE_ACCEPT4 + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_BYTESWAP_H + +/* Define to 1 if you have the declaration of `TIOCM_RTS', and to 0 if you + don't. */ +#undef HAVE_DECL_TIOCM_RTS + +/* Define to 1 if you have the declaration of `TIOCSRS485', and to 0 if you + don't. */ +#undef HAVE_DECL_TIOCSRS485 + +/* Define to 1 if you have the declaration of `__CYGWIN__', and to 0 if you + don't. */ +#undef HAVE_DECL___CYGWIN__ + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `getaddrinfo' function. */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the `inet_ntop' function. */ +#undef HAVE_INET_NTOP + +/* Define to 1 if you have the `inet_pton' function. */ +#undef HAVE_INET_PTON + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_SERIAL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MINIX_CONFIG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_TCP_H + +/* Define to 1 if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the `socket' function. */ +#undef HAVE_SOCKET + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAMS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WCHAR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINSOCK2_H + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ +#undef STDC_HEADERS + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable general extensions on macOS. */ +#ifndef _DARWIN_C_SOURCE +# undef _DARWIN_C_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable X/Open compliant socket functions that do not require linking + with -lxnet on HP-UX 11.11. */ +#ifndef _HPUX_ALT_XOPEN_SOCKET_API +# undef _HPUX_ALT_XOPEN_SOCKET_API +#endif +/* Identify the host operating system as Minix. + This macro does not affect the system headers' behavior. + A future release of Autoconf may stop defining this macro. */ +#ifndef _MINIX +# undef _MINIX +#endif +/* Enable general extensions on NetBSD. + Enable NetBSD compatibility extensions on Minix. */ +#ifndef _NETBSD_SOURCE +# undef _NETBSD_SOURCE +#endif +/* Enable OpenBSD compatibility extensions on NetBSD. + Oddly enough, this does nothing on OpenBSD. */ +#ifndef _OPENBSD_SOURCE +# undef _OPENBSD_SOURCE +#endif +/* Define to 1 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_SOURCE +# undef _POSIX_SOURCE +#endif +/* Define to 2 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_1_SOURCE +# undef _POSIX_1_SOURCE +#endif +/* Enable POSIX-compatible threading on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */ +#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ +# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */ +#ifndef __STDC_WANT_IEC_60559_BFP_EXT__ +# undef __STDC_WANT_IEC_60559_BFP_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */ +#ifndef __STDC_WANT_IEC_60559_DFP_EXT__ +# undef __STDC_WANT_IEC_60559_DFP_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */ +#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__ +# undef __STDC_WANT_IEC_60559_FUNCS_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */ +#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ +# undef __STDC_WANT_IEC_60559_TYPES_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */ +#ifndef __STDC_WANT_LIB_EXT2__ +# undef __STDC_WANT_LIB_EXT2__ +#endif +/* Enable extensions specified by ISO/IEC 24747:2009. */ +#ifndef __STDC_WANT_MATH_SPEC_FUNCS__ +# undef __STDC_WANT_MATH_SPEC_FUNCS__ +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable X/Open extensions. Define to 500 only if necessary + to make mbstate_t available. */ +#ifndef _XOPEN_SOURCE +# undef _XOPEN_SOURCE +#endif + + +/* Version number of package */ +#undef VERSION + +/* _ */ +#undef WINVER + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT32_T + +/* Define for Solaris 2.5.1 so the uint8_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT8_T + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to the type of a signed integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef int64_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to `int' if does not define. */ +#undef ssize_t + +/* Define to the type of an unsigned integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +#undef uint16_t + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef uint32_t + +/* Define to the type of an unsigned integer type of width exactly 8 bits if + such a type exists and the standard includes do not define it. */ +#undef uint8_t diff --git a/build/src/libmodbus/inc/config.h b/build/src/libmodbus/inc/config.h new file mode 100644 index 0000000..91492e8 --- /dev/null +++ b/build/src/libmodbus/inc/config.h @@ -0,0 +1,291 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the `accept4' function. */ +#undef HAVE_ACCEPT4 + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_BYTESWAP_H + +/* Define to 1 if you have the declaration of `TIOCM_RTS', and to 0 if you + don't. */ +#undef HAVE_DECL_TIOCM_RTS + +/* Define to 1 if you have the declaration of `TIOCSRS485', and to 0 if you + don't. */ +#undef HAVE_DECL_TIOCSRS485 + +/* Define to 1 if you have the declaration of `__CYGWIN__', and to 0 if you + don't. */ +#undef HAVE_DECL___CYGWIN__ + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `getaddrinfo' function. */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the `inet_ntop' function. */ +#undef HAVE_INET_NTOP + +/* Define to 1 if you have the `inet_pton' function. */ +#undef HAVE_INET_PTON + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_SERIAL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MINIX_CONFIG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_TCP_H + +/* Define to 1 if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the `socket' function. */ +#undef HAVE_SOCKET + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAMS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WCHAR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINSOCK2_H + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ +#undef STDC_HEADERS + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable general extensions on macOS. */ +#ifndef _DARWIN_C_SOURCE +# undef _DARWIN_C_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable X/Open compliant socket functions that do not require linking + with -lxnet on HP-UX 11.11. */ +#ifndef _HPUX_ALT_XOPEN_SOCKET_API +# undef _HPUX_ALT_XOPEN_SOCKET_API +#endif +/* Identify the host operating system as Minix. + This macro does not affect the system headers' behavior. + A future release of Autoconf may stop defining this macro. */ +#ifndef _MINIX +# undef _MINIX +#endif +/* Enable general extensions on NetBSD. + Enable NetBSD compatibility extensions on Minix. */ +#ifndef _NETBSD_SOURCE +# undef _NETBSD_SOURCE +#endif +/* Enable OpenBSD compatibility extensions on NetBSD. + Oddly enough, this does nothing on OpenBSD. */ +#ifndef _OPENBSD_SOURCE +# undef _OPENBSD_SOURCE +#endif +/* Define to 1 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_SOURCE +# undef _POSIX_SOURCE +#endif +/* Define to 2 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_1_SOURCE +# undef _POSIX_1_SOURCE +#endif +/* Enable POSIX-compatible threading on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */ +#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ +# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */ +#ifndef __STDC_WANT_IEC_60559_BFP_EXT__ +# undef __STDC_WANT_IEC_60559_BFP_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */ +#ifndef __STDC_WANT_IEC_60559_DFP_EXT__ +# undef __STDC_WANT_IEC_60559_DFP_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */ +#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__ +# undef __STDC_WANT_IEC_60559_FUNCS_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */ +#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ +# undef __STDC_WANT_IEC_60559_TYPES_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */ +#ifndef __STDC_WANT_LIB_EXT2__ +# undef __STDC_WANT_LIB_EXT2__ +#endif +/* Enable extensions specified by ISO/IEC 24747:2009. */ +#ifndef __STDC_WANT_MATH_SPEC_FUNCS__ +# undef __STDC_WANT_MATH_SPEC_FUNCS__ +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable X/Open extensions. Define to 500 only if necessary + to make mbstate_t available. */ +#ifndef _XOPEN_SOURCE +# undef _XOPEN_SOURCE +#endif + + +/* Version number of package */ +#undef VERSION + +/* _ */ +#undef WINVER + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT32_T + +/* Define for Solaris 2.5.1 so the uint8_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT8_T + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to the type of a signed integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef int64_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to `int' if does not define. */ +#undef ssize_t + +/* Define to the type of an unsigned integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +#undef uint16_t + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef uint32_t + +/* Define to the type of an unsigned integer type of width exactly 8 bits if + such a type exists and the standard includes do not define it. */ +#undef uint8_t diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..b185652 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,9 @@ +add_executable(hoymilesSunspecInterface_exec main.cpp) + +include_directories(libmodbus/inc) +add_subdirectory(libmodbus) +target_link_libraries(hoymilesSunspecInterface_exec libmodbus) + +include_directories(hoymiles/inc hoymiles/inc/portParameters hoymiles/inc/sunspecParameters) +add_subdirectory(hoymiles) +target_link_libraries(hoymilesSunspecInterface_exec libhoymiles) \ No newline at end of file diff --git a/src/hoymiles/CMakeLists.txt b/src/hoymiles/CMakeLists.txt new file mode 100644 index 0000000..d97681f --- /dev/null +++ b/src/hoymiles/CMakeLists.txt @@ -0,0 +1,8 @@ +include_directories(inc inc/portParameters inc/sunspecParameters) + +file(GLOB SOURCES src/*.cpp src/portParameters/*.cpp src/sunspecParameters/*.cpp) + +add_library(libhoymiles STATIC ${SOURCES}) + +include_directories(${PROJECT_SOURCE_DIR}/libmodbus/inc) +target_link_libraries(libhoymiles libmodbus) \ No newline at end of file diff --git a/src/hoymiles/inc/dtu.h b/src/hoymiles/inc/dtu.h new file mode 100644 index 0000000..84de060 --- /dev/null +++ b/src/hoymiles/inc/dtu.h @@ -0,0 +1,39 @@ +#ifndef DTU_H +#define DTU_H + +#include +#include +#include + +#include "microinverter.h" +#include "modbus.h" + +class Dtu { + private: + modbus_t *modbus; + + std::vector microinverters; + + void populateMicroinverters(); + + bool connected; + + public: + Dtu(const char *deviceAddress); + + std::pair getMicroinverterBySerialNumber(long long serialNumber); + + bool isConnected(); + + void updateMicroinverters(std::vector ¶metersToGet, bool allParameters, std::vector µinvertersToGet); + + void printMicroinverters(std::vector ¶metersToGet, bool allParameters, std::vector µinvertersToGet, bool shortNames, bool printTodayProduction, bool printTotalProduction); + + void setStatusMicroinverters(uint16_t value, std::string statusName, std::vector& microinvertersToSet); + + bool empty(); + + ~Dtu(); +}; + +#endif \ No newline at end of file diff --git a/src/hoymiles/inc/microinverter.h b/src/hoymiles/inc/microinverter.h new file mode 100644 index 0000000..0eaf563 --- /dev/null +++ b/src/hoymiles/inc/microinverter.h @@ -0,0 +1,48 @@ +#ifndef MICROINVERTER_H +#define MICROINVERTER_H + +#include +#include +#include + +#include "modbus.h" +#include "port.h" +#include "sunspec.h" + +class Microinverter { + private: + modbus_t *modbus; + + Sunspec sunspec; + + int startAddress; + + int statusStartAddress; + + public: + Microinverter(modbus_t *modbus, int startAddress, long long serialNumber); + + long long serialNumber; + + int age; + + std::vector ports; + + // void updatePorts(std::vector ¶metersToGet, bool allParameters); + + void updateParameters(std::vector ¶metersToGet, bool allParameters); + + void updateStatusParameters(); + + void printPorts(std::vector ¶metersToGet, bool allParameters, bool shortNames); + + long long getTodayProduction(); + + long long getTotalProduction(); + + void setStatus(std::vector> portsToSet, std::string statusName); + + void setStatusWholeMicroinverter(uint16_t value, std::string statusName); +}; + +#endif \ No newline at end of file diff --git a/src/hoymiles/inc/port.h b/src/hoymiles/inc/port.h new file mode 100644 index 0000000..bd60e81 --- /dev/null +++ b/src/hoymiles/inc/port.h @@ -0,0 +1,49 @@ +#ifndef PORT_H +#define PORT_H + +#include +#include +#include + +#include "portParametersGeneric.h" +#include "portParameters.h" +#include "modbus.h" + +class Port { + private: + void populateParameters(); + + void fixCurrent(); + bool currentFixed; + + // void increaseParametersAge(); + + public: + Port(int portStartAddress); + + int portStartAddress; + + int statusPortStartAddress; + + std::vector> parameters; + + std::vector> statusParameters; + + std::pair, bool> getParameterByName(std::string name); + + std::pair, bool> getStatusByName(std::string name); + + // void updateParameters(std::vector ¶metersToGet, bool allParameters); + + void setParametersFromMicroinverterArray(uint16_t *registers, int addressOffset); + + void setStatusesFromMicroinverterArray(uint16_t *registers, int addressOffset); + + void printParameters(std::vector ¶metersToGet, bool allParameters, bool shortNames); + + void turnOff(modbus_t *modbus); + + bool isOff(modbus_t *modbus); +}; + +#endif \ No newline at end of file diff --git a/src/hoymiles/inc/portParameters/portParameters.h b/src/hoymiles/inc/portParameters/portParameters.h new file mode 100644 index 0000000..cd15028 --- /dev/null +++ b/src/hoymiles/inc/portParameters/portParameters.h @@ -0,0 +1,94 @@ +#ifndef PORTPARAMETERS_H +#define PORTPARAMETERS_H + +#include "portParametersGeneric.h" + +class PortParameterMicroinverterSerialNumber : public PortParameterInt { + private: + void getValueFromRegisters(uint16_t *registers, int addressOffset); + + public: + PortParameterMicroinverterSerialNumber(); +}; + +class PortParameterPortNumber : public PortParameterInt { + public: + PortParameterPortNumber(); +}; + +class PortParameterPvVoltage : public PortParameterFloat { + public: + PortParameterPvVoltage(); +}; + +class PortParameterPvCurrentMi : public PortParameterFloat { + public: + PortParameterPvCurrentMi(); +}; + +class PortParameterPvCurrentHm : public PortParameterFloat { + public: + PortParameterPvCurrentHm(); +}; + +class PortParameterGridVoltage : public PortParameterFloat { + public: + PortParameterGridVoltage(); +}; + +class PortParameterGridFrequency : public PortParameterFloat { + public: + PortParameterGridFrequency(); +}; + +class PortParameterPvPower : public PortParameterFloat { + public: + PortParameterPvPower(); +}; + +class PortParameterTodayProduction : public PortParameterInt { + public: + PortParameterTodayProduction(); +}; + +class PortParameterTotalProduction : public PortParameterInt { + public: + PortParameterTotalProduction(); +}; + +class PortParameterTemperature : public PortParameterFloat { + public: + PortParameterTemperature(); +}; + +class PortParameterOperatingStatus : public PortParameterInt { + public: + PortParameterOperatingStatus(); +}; + +class PortParameterAlarmCode : public PortParameterInt { + public: + PortParameterAlarmCode(); +}; + +class PortParameterAlarmCount : public PortParameterInt { + public: + PortParameterAlarmCount(); +}; + +class PortParameterLinkStatus : public PortParameterInt { + public: + PortParameterLinkStatus(); +}; + +class PortParameterOnOff : public PortParameterInt { + public: + PortParameterOnOff(); +}; + +class PortParameterLimitActivePower : public PortParameterInt { + public: + PortParameterLimitActivePower(); +}; + +#endif \ No newline at end of file diff --git a/src/hoymiles/inc/portParameters/portParametersGeneric.h b/src/hoymiles/inc/portParameters/portParametersGeneric.h new file mode 100644 index 0000000..7426e51 --- /dev/null +++ b/src/hoymiles/inc/portParameters/portParametersGeneric.h @@ -0,0 +1,77 @@ +#ifndef PORTPARAMETERSGENERIC_H +#define PORTPARAMETERSGENERIC_H + +#include +#include +#include + +struct _modbus; +typedef _modbus modbus_t; + +class PortParameter { + protected: + uint16_t parameterAddressOffset; + int registerSize; + + std::string unit; + + bool r; + bool w; + + public: + PortParameter(std::string name, std::string shortName, std::string unit, bool r, bool w, uint16_t parameterAddressOffset, int registerSize); + + virtual ~PortParameter(); + + enum PortParameterValueType { Int, Float }; + + union PortParameterValue { + long long i; + float f; + }; + + protected: + PortParameterValueType valueType; + PortParameterValue value; + + public: + std::string name; + std::string shortName; + + // int age; + + std::pair getValue(); + + PortParameter& writeValue(uint16_t value, modbus_t *modbus, int portStartAddress); + + virtual std::string getOutputValue(); + + virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); + + // void updateValue(std::shared_ptr modubs, uint16_t portStartAddress); +}; + +class PortParameterFloat : public PortParameter { + protected: + int decimalPlaces; + + public: + PortParameterFloat(std::string name, std::string shortName, std::string unit, bool r, bool w, int decimalPlaces, uint16_t parameterAddressOffset, int registerSize); + + std::string getOutputValue(); + + virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); +}; + +class PortParameterInt : public PortParameter { + protected: + + public: + PortParameterInt(std::string name, std::string shortName, std::string unit, bool r, bool w, uint16_t parameterAddressOffset, int registerSize); + + std::string getOutputValue(); + + virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); +}; + +#endif \ No newline at end of file diff --git a/src/hoymiles/inc/sunspec.h b/src/hoymiles/inc/sunspec.h new file mode 100644 index 0000000..a82d678 --- /dev/null +++ b/src/hoymiles/inc/sunspec.h @@ -0,0 +1,37 @@ +#ifndef SUNSPEC_H +#define SUNSPEC_H + +#include +#include +#include +#include + +#include "modbus.h" +#include "sunspecParametersGeneric.h" + +class Sunspec { + protected: + modbus_t *modbus; + + std::vector> parameters; + + std::string manufacturer; + std::string model; + std::string version; + + std::string serialNumber; + uint16_t deviceAddress; + + int sunspecAddress; + + void setValues(); + + void populateParameters(); + + public: + Sunspec(int address, modbus_t *modbus); + + uint16_t getAddress(); +}; + +#endif \ No newline at end of file diff --git a/src/hoymiles/inc/sunspecParameters/sunspecParameters.h b/src/hoymiles/inc/sunspecParameters/sunspecParameters.h new file mode 100644 index 0000000..cdf4bed --- /dev/null +++ b/src/hoymiles/inc/sunspecParameters/sunspecParameters.h @@ -0,0 +1,15 @@ +#ifndef SUNSPEC_PARAMETERS_H +#define SUNSPEC_PARAMETERS_H + +#include "sunspecParametersGeneric.h" + +class SunspecParameterManufacturer : public SunspecParameterString32 { + protected: + + public: + SunspecParameterManufacturer(); + + void getValueFromRegisters(uint16_t *registers, int addressOffset); +}; + +#endif \ No newline at end of file diff --git a/src/hoymiles/inc/sunspecParameters/sunspecParametersGeneric.h b/src/hoymiles/inc/sunspecParameters/sunspecParametersGeneric.h new file mode 100644 index 0000000..aba5e8d --- /dev/null +++ b/src/hoymiles/inc/sunspecParameters/sunspecParametersGeneric.h @@ -0,0 +1,124 @@ +#ifndef SUNSPEC_PARAMETERS_GENERIC_H +#define SUNSPEC_PARAMETERS_GENERIC_H + +#include +#include + +class SunspecParameter { + protected: + std::string name; + int registerAddressOffset; + int registerSize; + + public: + SunspecParameter(std::string name, int registerAddressOffset, int registerSize); + + virtual ~SunspecParameter(); + + enum SunspecValueType { uint32, uint16, string32, string16, sunssf, int16, acc32, float32, enum16 }; + + union SunspecValue { + uint32_t u32; + uint16_t u16; + uint16_t ssf; + int i16; + uint16_t a32; + float f; + uint16_t e16; + }; + + protected: + SunspecValueType valueType; + SunspecValue value; + + public: + + virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); + + std::pair getValue(); +}; + +// class SunspecParameterUint32 : public SunspecParameter { +// protected: + +// public: +// SunspecParameterUint32(std::string name, int registerAddressOffset, int registerSize); + +// virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); +// }; + +// class SunspecParameterUint16 : public SunspecParameter { +// protected: + +// public: +// SunspecParameterUint16(std::string name, int registerAddressOffset, int registerSize); + +// virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); +// }; + +class SunspecParameterString32 : public SunspecParameter { + protected: + std::string value; + + public: + SunspecParameterString32(std::string name, int registerAddressOffset, int registerSize); + + virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); +}; + +// class SunspecParameterString16 : public SunspecParameter { +// protected: +// std::string value; + +// public: +// SunspecParameterString16(std::string name, int registerAddressOffset, int registerSize); + +// virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); +// }; + +// class SunspecParameterSunssf : public SunspecParameter { +// protected: + +// public: +// SunspecParameterSunssf(std::string name, int registerAddressOffset, int registerSize); + +// virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); +// }; + +// class SunspecParameterInt16 : public SunspecParameter { +// protected: + +// public: +// SunspecParameterInt16(std::string name, int registerAddressOffset, int registerSize); + +// virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); +// }; + +// class SunspecParameterAcc32 : public SunspecParameter { +// protected: + +// public: +// SunspecParameterAcc32(std::string name, int registerAddressOffset, int registerSize); + +// virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); +// }; + +// class SunspecParameterFloat32 : public SunspecParameter { +// protected: + +// public: +// SunspecParameterFloat32(std::string name, int registerAddressOffset, int registerSize); + +// virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); +// }; + +// class SunspecParameterEnum16 : public SunspecParameter { +// protected: + +// public: +// SunspecParameterEnum16(std::string name, int registerAddressOffset, int registerSize); + +// virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); +// }; + +#endif \ No newline at end of file diff --git a/src/hoymiles/src/dtu.cpp b/src/hoymiles/src/dtu.cpp new file mode 100644 index 0000000..1c4a889 --- /dev/null +++ b/src/hoymiles/src/dtu.cpp @@ -0,0 +1,152 @@ +#include +#include +#include +#include + +#include "modbus.h" + +#include "dtu.h" +#include "microinverter.h" + +#include "portParameters.h" + +Dtu::Dtu(const char *deviceAddress) { + this->modbus = modbus_new_rtu(deviceAddress, 9600, 'N', 8, 1); + modbus_rtu_set_serial_mode(this->modbus, MODBUS_RTU_RS485); + + modbus_set_debug(this->modbus, 1); + + this->connected = false; + int temp = modbus_connect(this->modbus); + if (temp == -1) { + std::cerr << "NOT CONNECTED" << std::endl; + } + else { + this->connected = true; + modbus_set_slave(this->modbus, 101); + this->populateMicroinverters(); + } +} + +bool Dtu::isConnected() { + return this->connected; +} + +Dtu::~Dtu() { + modbus_close(this->modbus); +} + +void Dtu::populateMicroinverters() { + int portStartAddress = 0x4000; + uint16_t registers[19]; + + int registerCount; + registerCount = modbus_read_registers(this->modbus, portStartAddress, 19, registers); + + if (registerCount == -1) { + return; + } + + while (registerCount != -1) { + if(registers[0] != 12) { + break; + } + + Port port{portStartAddress}; + port.setParametersFromMicroinverterArray(registers, 0); + + if (!this->getMicroinverterBySerialNumber(port.getParameterByName("microinverterSerialNumber").first.get()->getValue().first.i).second) { + Microinverter microinverter{this->modbus, portStartAddress, port.getParameterByName("microinverterSerialNumber").first.get()->getValue().first.i}; + this->microinverters.push_back(microinverter); + } + + this->getMicroinverterBySerialNumber(port.getParameterByName("microinverterSerialNumber").first.get()->getValue().first.i).first->ports.push_back(port); + + portStartAddress += 0x0019; + + registerCount = modbus_read_registers(this->modbus, portStartAddress, 19, registers); + } +} + +std::pair Dtu::getMicroinverterBySerialNumber(long long serialNumber) { + std::vector::iterator microinvertersIterator = this->microinverters.begin(); + while (microinvertersIterator != this->microinverters.end()) { + if (microinvertersIterator->serialNumber == serialNumber) { + return std::pair(&*microinvertersIterator, true); + } else { + microinvertersIterator++; + } + } + return std::pair(&*microinvertersIterator, false); +} + +void Dtu::updateMicroinverters(std::vector ¶metersToGet, bool allParameters, std::vector µinvertersToGet) { + if (microinvertersToGet.empty()) { + std::vector::iterator microinvertersIterator = this->microinverters.begin(); + while (microinvertersIterator != this->microinverters.end()) { + microinvertersToGet.push_back(microinvertersIterator->serialNumber); + microinvertersIterator++; + } + } + + std::vector::iterator microinvertersToGetIterator = microinvertersToGet.begin(); + while (microinvertersToGetIterator != microinvertersToGet.end()) { + std::pair microinverterPair = this->getMicroinverterBySerialNumber(*microinvertersToGetIterator); + if (microinverterPair.second) { + microinverterPair.first->updateParameters(parametersToGet, allParameters); + microinverterPair.first->updateStatusParameters(); + } + microinvertersToGetIterator++; + } +} + +void Dtu::printMicroinverters(std::vector ¶metersToGet, bool allParameters, std::vector µinvertersToGet, bool shortNames, bool printTodayProduction, bool printTotalProduction) { + if (microinvertersToGet.empty()) { + std::vector::iterator microinvertersIterator = this->microinverters.begin(); + while (microinvertersIterator != this->microinverters.end()) { + microinvertersToGet.push_back(microinvertersIterator->serialNumber); + microinvertersIterator++; + } + } + + std::vector::iterator microinvertersToGetIterator = microinvertersToGet.begin(); + while (microinvertersToGetIterator != microinvertersToGet.end()) { + std::pair microinverterPair = this->getMicroinverterBySerialNumber(*microinvertersToGetIterator); + if (microinverterPair.second) { + std::cout << " " << "Microinverter: " << microinverterPair.first->serialNumber << std::endl; + std::cout << " " << "Microinverter Data Age: " << microinverterPair.first->age << std::endl; + if (printTodayProduction) { + std::cout << " " << "TodayProduction: " << microinverterPair.first->getTodayProduction() << "Wh" << std::endl; + } + if (printTotalProduction) { + std::cout << " " << "TotalProduction: " << microinverterPair.first->getTotalProduction() << "Wh" << std::endl; + } + microinverterPair.first->printPorts(parametersToGet, allParameters, shortNames); + std::cout << std::endl; + } + microinvertersToGetIterator++; + } +} + +void Dtu::setStatusMicroinverters(uint16_t value, std::string statusName, std::vector& microinvertersToSet) { + if (microinvertersToSet.empty()) { + std::vector::iterator microinvertersIterator = this->microinverters.begin(); + while (microinvertersIterator != this->microinverters.end()) { + microinvertersToSet.push_back(microinvertersIterator->serialNumber); + microinvertersIterator++; + } + } + + std::vector::iterator microinvertersToSetIterator = microinvertersToSet.begin(); + while(microinvertersToSetIterator != microinvertersToSet.end()) { + std::pair microinverterPair = this->getMicroinverterBySerialNumber(*microinvertersToSetIterator); + if(microinverterPair.second) { + microinverterPair.first->setStatusWholeMicroinverter(value, statusName); + } + microinvertersToSetIterator++; + } +} + +bool Dtu::empty() { + return this->microinverters.empty(); +} \ No newline at end of file diff --git a/src/hoymiles/src/microinverter.cpp b/src/hoymiles/src/microinverter.cpp new file mode 100644 index 0000000..c7c39c8 --- /dev/null +++ b/src/hoymiles/src/microinverter.cpp @@ -0,0 +1,139 @@ +#include +#include +#include + +#include "modbus.h" + +#include "microinverter.h" +#include "port.h" +#include "sunspec.h" + +Microinverter::Microinverter(modbus_t *modbus, int startAddress, long long serialNumber) : sunspec(40000, modbus) { + this->modbus = modbus; + this->startAddress = startAddress; + this->serialNumber = serialNumber; + + this->statusStartAddress = (((this->startAddress - 0x4000) / 0x0019) * 6) + 0xd006; + + this->age = 0; +} + +// void Microinverter::updatePorts(std::vector ¶metersToGet, bool allParameters) { +// int registersToRead = (this->ports.size() * 40) / 2; +// uint16_t registersJoined[registersToRead]; + +// int registerCount = this->modbus.get()->modbus_read_holding_registers(this->startAddress, registersToRead, registersJoined); +// } + +void Microinverter::updateParameters(std::vector ¶metersToGet, bool allParameters) { + int portsRead = 0; + while (portsRead < this->ports.size()) { + int portsToRead = 0; + while (portsToRead * 0x0019 < (128 - 0x0019) && (portsToRead + portsRead) < this->ports.size()) { + portsToRead++; + } + + int registersToRead = (portsToRead * 0x0019); + uint16_t registers[registersToRead]; + + int registerCount; + registerCount = modbus_read_input_registers(this->modbus, this->startAddress + (portsRead * 0x0019), registersToRead, registers); + + if (registerCount != 0) { + this->age++; + return; + } + + for (int i{0}; i < portsToRead; i++) { + this->ports.at(i + portsRead).setParametersFromMicroinverterArray(registers, i * 0x0019); + } + + portsRead += portsToRead; + } +} + +void Microinverter::updateStatusParameters() { + int portsRead = 0; + while (portsRead < this->ports.size()) { + int portsToRead = 0; + while (portsToRead * 6 < (128 - 6) && (portsToRead + portsRead) < this->ports.size()) { + portsToRead++; + } + + int registersToRead = (portsToRead * 6); + uint16_t registers[registersToRead]; + + int registerCount; + registerCount = modbus_read_input_registers(this->modbus, this->statusStartAddress + (portsRead * 6), registersToRead, registers); + + if (registerCount != 0) { + this->age++; + return; + } + else { + this->age = 0; + } + + for (int i{0}; i < portsToRead; i++) { + this->ports.at(i + portsRead).setStatusesFromMicroinverterArray(registers, i * 6); + } + + portsRead += portsToRead; + } +} + +void Microinverter::printPorts(std::vector ¶metersToGet, bool allParameters, bool shortNames) { + std::vector::iterator portsIterator = this->ports.begin(); + while (portsIterator != this->ports.end()) { + portsIterator->printParameters(parametersToGet, allParameters, shortNames); + std::cout << std::endl; + portsIterator++; + } +} + +long long Microinverter::getTodayProduction() { + long long result{0}; + + std::vector::iterator portsIterator = this->ports.begin(); + while (portsIterator != this->ports.end()) { + result += portsIterator->getParameterByName("todayProduction").first.get()->getValue().first.i; + portsIterator++; + } + + return result; +} + +long long Microinverter::getTotalProduction() { + long long result{0}; + + std::vector::iterator portsIterator = this->ports.begin(); + while (portsIterator != this->ports.end()) { + result += portsIterator->getParameterByName("totalProduction").first.get()->getValue().first.i; + portsIterator++; + } + + return result; +} + +void Microinverter::setStatus(std::vector> portsToSet, std::string statusName) { + std::vector>::iterator portsToSetIterator = portsToSet.begin(); + while(portsToSetIterator != portsToSet.end()) { + try { + if(this->ports.at(portsToSetIterator->first).getStatusByName(statusName).second) { + this->ports.at(portsToSetIterator->first).getStatusByName(statusName).first->writeValue(portsToSetIterator->second, this->modbus, this->statusStartAddress); + } + } + catch(const std::out_of_range& outOfRange) { + std::cerr << outOfRange.what() << std::endl; + } + portsToSetIterator++; + } +} + +void Microinverter::setStatusWholeMicroinverter(uint16_t value, std::string statusName) { + if(this->ports.begin() != this->ports.end()) { + if(this->ports.begin()->getStatusByName(statusName).second) { + this->ports.begin()->getStatusByName(statusName).first.get()->writeValue(value, this->modbus, this->ports.begin()->statusPortStartAddress); + } + } +} \ No newline at end of file diff --git a/src/hoymiles/src/port.cpp b/src/hoymiles/src/port.cpp new file mode 100644 index 0000000..acc8383 --- /dev/null +++ b/src/hoymiles/src/port.cpp @@ -0,0 +1,223 @@ +#include +#include +#include +#include +#include + +#include "modbus.h" + +#include "port.h" +#include "portParameters.h" + +Port::Port(int portStartAddress) { + this->portStartAddress = portStartAddress; + + this->statusPortStartAddress = (((this->portStartAddress - 0x4000) / 0x0019) * 6) + 0xd006; + + this->currentFixed = false; + + this->populateParameters(); +} + +void Port::populateParameters() { + this->parameters.push_back(std::make_shared()); + + this->parameters.push_back(std::make_shared()); + + this->parameters.push_back(std::make_shared()); + + this->parameters.push_back(std::make_shared()); + + this->parameters.push_back(std::make_shared()); + + this->parameters.push_back(std::make_shared()); + + this->parameters.push_back(std::make_shared()); + + this->parameters.push_back(std::make_shared()); + + this->parameters.push_back(std::make_shared()); + + this->parameters.push_back(std::make_shared()); + + this->parameters.push_back(std::make_shared()); + + this->parameters.push_back(std::make_shared()); + + this->parameters.push_back(std::make_shared()); + + this->parameters.push_back(std::make_shared()); + + this->parameters.push_back(std::make_shared()); + + this->statusParameters.push_back(std::make_shared()); + + this->statusParameters.push_back(std::make_shared()); +} + +std::pair, bool> Port::getParameterByName(std::string name) { + std::pair, bool> result; + result.second = false; + + std::vector>::iterator parametersIterator = this->parameters.begin(); + while (parametersIterator != this->parameters.end() && !result.second) { + if (parametersIterator->get()->name == name) { + result.first = *parametersIterator; + result.second = true; + } + parametersIterator++; + } + + return result; +} + +std::pair, bool> Port::getStatusByName(std::string name) { + std::pair, bool> result; + result.second = false; + + std::vector>::iterator parametersIterator = this->statusParameters.begin(); + while (parametersIterator != this->statusParameters.end() && !result.second) { + if (parametersIterator->get()->name == name) { + result.first = *parametersIterator; + result.second = true; + } + parametersIterator++; + } + + return result; +} + +void Port::fixCurrent() { + if (this->currentFixed) { + return; + } + + if (!this->getParameterByName("pvCurrentMI").second != !this->getParameterByName("pvCurrentHM").second) { + this->currentFixed = true; + return; + } + + if (this->getParameterByName("pvVoltage").second && this->getParameterByName("pvPower").second) { + if (this->getParameterByName("pvCurrentMI").second && this->getParameterByName("pvCurrentHM").second) { + if (this->getParameterByName("pvPower").first->getValue().first.f > this->getParameterByName("pvVoltage").first->getValue().first.f * this->getParameterByName("pvCurrentMI").first->getValue().first.f) { + this->parameters.erase(std::find(this->parameters.begin(), this->parameters.end(), this->getParameterByName("pvCurrentHM").first)); + } else { + this->parameters.erase(std::find(this->parameters.begin(), this->parameters.end(), this->getParameterByName("pvCurrentMI").first)); + } + this->currentFixed = true; + } + } +} + +// void Port::increaseParametersAge() { +// std::vector>::iterator parametersIterator = this->parameters.begin(); +// while(parametersIterator != this->parameters.end()) { +// parametersIterator->get()->age++; +// parametersIterator++; +// } +// } + +// void Port::updateParameters(std::vector ¶metersToGet, bool allParameters) { +// this->increaseParametersAge(); + +// if (allParameters && parametersToGet.size() < this->parameters.size()) { +// std::vector>::iterator parametersIterator = this->parameters.begin(); +// while (parametersIterator != this->parameters.end()) { +// if (std::find(parametersToGet.begin(), parametersToGet.end(), parametersIterator->get()->name) == parametersToGet.end()) { +// parametersToGet.push_back(parametersIterator->get()->name); +// } +// parametersIterator++; +// } +// } + +// std::vector::iterator parametersToGetIterator = parametersToGet.begin(); +// while (parametersToGetIterator != parametersToGet.end()) { +// std::pair, bool> parameterPair; + +// parameterPair = this->getParameterByName(*parametersToGetIterator); +// if (parameterPair.second) { +// parameterPair.first->updateValue(this->modbus, this->portStartAddress); +// } + +// this->fixCurrent(); + +// parametersToGetIterator++; +// } +// } + +void Port::setParametersFromMicroinverterArray(uint16_t *registers, int addressOffset) { + std::vector>::iterator parametersIterator = this->parameters.begin(); + while (parametersIterator != this->parameters.end()) { + parametersIterator->get()->getValueFromRegisters(registers, addressOffset); + parametersIterator++; + } + this->fixCurrent(); +} + +void Port::setStatusesFromMicroinverterArray(uint16_t *registers, int addressOffset) { + std::vector>::iterator parametersIterator = this->statusParameters.begin(); + while (parametersIterator != this->statusParameters.end()) { + parametersIterator->get()->getValueFromRegisters(registers, addressOffset); + parametersIterator++; + } +} + +void Port::printParameters(std::vector ¶metersToGet, bool allParameters, bool shortNames) { + if (allParameters && parametersToGet.size() < this->parameters.size()) { + std::vector>::iterator parametersIterator = this->parameters.begin(); + while (parametersIterator != this->parameters.end()) { + std::string temp{parametersIterator->get()->name}; + if (std::find(parametersToGet.begin(), parametersToGet.end(), parametersIterator->get()->name) == parametersToGet.end()) { + parametersToGet.push_back(parametersIterator->get()->name); + } + parametersIterator++; + } + } + + std::vector::iterator parametersToGetIterator = parametersToGet.begin(); + if (parametersToGetIterator != parametersToGet.end()) { + std::cout << " |"; + } + + while (parametersToGetIterator != parametersToGet.end()) { + if (*parametersToGetIterator == "microinverterSerialNumber") { + parametersToGetIterator++; + continue; + } + std::pair, bool> parameterPair; + + parameterPair = this->getParameterByName(*parametersToGetIterator); + if (parameterPair.second) { + std::cout << " "; + if (shortNames) { + std::cout << parameterPair.first->shortName; + } else { + std::cout << parameterPair.first->name; + } + std::cout << ": " << parameterPair.first->getOutputValue() << " |"; + } + parametersToGetIterator++; + } + + std::vector>::iterator statusesToGetIterator = this->statusParameters.begin(); + while (statusesToGetIterator != this->statusParameters.end()) { + std::cout << " "; + if (shortNames) { + std::cout << statusesToGetIterator->get()->shortName; + } else { + std::cout << statusesToGetIterator->get()->name; + } + std::cout << ": " << statusesToGetIterator->get()->getOutputValue() << " |"; + statusesToGetIterator++; + } +} + +void Port::turnOff(modbus_t *modbus) { this->getStatusByName("onOff").first.get()->writeValue(0, modbus, this->statusPortStartAddress); } + +bool Port::isOff(modbus_t *modbus) { + if (this->getStatusByName("onOff").first.get()->getValue().first.i == 1) { + return true; + } else { + return false; + } +} \ No newline at end of file diff --git a/src/hoymiles/src/portParameters/portParameters.cpp b/src/hoymiles/src/portParameters/portParameters.cpp new file mode 100644 index 0000000..d7bbb43 --- /dev/null +++ b/src/hoymiles/src/portParameters/portParameters.cpp @@ -0,0 +1,51 @@ +#include +#include +#include +#include + +#include "portParameters.h" + +PortParameterMicroinverterSerialNumber::PortParameterMicroinverterSerialNumber() : PortParameterInt("microinverterSerialNumber", "mSN", "", true, false, 0x0001, 3) {} + +void PortParameterMicroinverterSerialNumber::getValueFromRegisters(uint16_t *registers, int addressOffset) { + std::string readValueString = ""; + for (int i{0}; i < this->registerSize; i++) { + std::stringstream readValueStringStream; + readValueStringStream << std::hex << (int) ((registers[addressOffset + this->parameterAddressOffset + i] & 0xff00) >> 8); + readValueStringStream << std::hex << (int) (registers[addressOffset + this->parameterAddressOffset + i] & 0x00ff); + readValueString.append(readValueStringStream.str()); + } + this->value.i = std::stoll(readValueString); +} + +PortParameterPortNumber::PortParameterPortNumber() : PortParameterInt("portNumber", "pN", "", true, false, 0x0004, 1) {} + +PortParameterPvVoltage::PortParameterPvVoltage() : PortParameterFloat("pvVoltage", "pvU", "V", true, false, 1, 0x0005, 1) {} + +PortParameterPvCurrentMi::PortParameterPvCurrentMi() : PortParameterFloat("pvCurrentMI", "pvIMI", "A", true, false, 1, 0x0006, 1) {} + +PortParameterPvCurrentHm::PortParameterPvCurrentHm() : PortParameterFloat("pvCurrentHM", "pvIHM", "A", true, false, 2, 0x0006, 1) {} + +PortParameterGridVoltage::PortParameterGridVoltage() : PortParameterFloat("gridVoltage", "gU", "V", true, false, 1, 0x0007, 1) {} + +PortParameterGridFrequency::PortParameterGridFrequency() : PortParameterFloat("gridFrequency", "gF", "Hz", true, false, 2, 0x0008, 1) {} + +PortParameterPvPower::PortParameterPvPower() : PortParameterFloat("pvPower", "pvP", "W", true, false, 1, 0x0009, 1) {} + +PortParameterTodayProduction::PortParameterTodayProduction() : PortParameterInt("todayProduction", "tdP", "Wh", true, false, 0x000A, 1) {} + +PortParameterTotalProduction::PortParameterTotalProduction() : PortParameterInt("totalProduction", "ttP", "Wh", true, false, 0x000B, 2) {} + +PortParameterTemperature::PortParameterTemperature() : PortParameterFloat("temperature", "t", "C", true, false, 1, 0x000D, 1) {} + +PortParameterOperatingStatus::PortParameterOperatingStatus() : PortParameterInt("operatingStatus", "oS", "", true, false, 0x000e, 1) {} + +PortParameterAlarmCode::PortParameterAlarmCode() : PortParameterInt("alarmCode", "aC", "", true, false, 0x000f, 1) {} + +PortParameterAlarmCount::PortParameterAlarmCount() : PortParameterInt("alarmCount", "aCnt", "", true, false, 0x0010, 1) {} + +PortParameterLinkStatus::PortParameterLinkStatus() : PortParameterInt("linkStatus", "lS", "", true, false, 0x011, 1) {} + +PortParameterOnOff::PortParameterOnOff() : PortParameterInt("onOff", "of", "", true, true, 0x0000, 1) {} + +PortParameterLimitActivePower::PortParameterLimitActivePower() : PortParameterInt("limitActivePower", "lAP", "%", true, true, 0x0001, 1) {} \ No newline at end of file diff --git a/src/hoymiles/src/portParameters/portParametersGeneric.cpp b/src/hoymiles/src/portParameters/portParametersGeneric.cpp new file mode 100644 index 0000000..717aadd --- /dev/null +++ b/src/hoymiles/src/portParameters/portParametersGeneric.cpp @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include + +#include "modbus.h" + +#include "portParametersGeneric.h" + +PortParameter::PortParameter(std::string name, std::string shortName, std::string unit, bool r, bool w, uint16_t parameterAddressOffset, int registerSize) { + this->name = name; + this->shortName = shortName; + this->unit = unit; + + this->r = r; + this->w = w; + + this->parameterAddressOffset = parameterAddressOffset; + this->registerSize = registerSize; +} + +PortParameter::~PortParameter() {} + +void PortParameter::getValueFromRegisters(uint16_t *readArray, int portOffset) {} + +std::pair PortParameter::getValue() { + return std::pair(this->value, this->valueType); +} + +PortParameter& PortParameter::writeValue(uint16_t value, modbus_t *modbus, int portStartAddress) { + int writeCount; + writeCount = modbus_write_register(modbus, this->parameterAddressOffset + portStartAddress, value); + return *this; +} + +std::string PortParameter::getOutputValue() { + return "yeet"; +} + +PortParameterFloat::PortParameterFloat(std::string name, std::string shortName, std::string unit, bool r, bool w, int decimalPlaces, uint16_t parameterAddressOffset, int registerSize) : PortParameter(name, shortName, unit, r, w, parameterAddressOffset, registerSize) { + this->decimalPlaces = decimalPlaces; + + this->valueType = Float; + + this->value.f = 0; +} + +void PortParameterFloat::getValueFromRegisters(uint16_t *registers, int addressOffset) { + std::string readValueString{""}; + for(int i{0}; iregisterSize; i++) { + std::stringstream readValueStringStream; + readValueStringStream << (int) registers[addressOffset + this->parameterAddressOffset + i]; + readValueString.append(readValueStringStream.str().c_str()); + } + this->value.f = std::stoll(readValueString) / std::pow(10, this->decimalPlaces); +} + +std::string PortParameterFloat::getOutputValue() { + std::stringstream valueStringStream; + valueStringStream << std::fixed << std::setprecision(this->decimalPlaces) << this->value.f; + return valueStringStream.str().append(this->unit.c_str()); +} + +PortParameterInt::PortParameterInt(std::string name, std::string shortName, std::string unit, bool r, bool w, uint16_t parameterAddressOffset, int registerSize) : PortParameter(name, shortName, unit, r, w, parameterAddressOffset, registerSize) { + this->valueType = Int; + + this->value.i = 0; +} + +void PortParameterInt::getValueFromRegisters(uint16_t *registers, int addressOffset) { + std::string readValueString{""}; + for (int i{0}; i < this->registerSize; i++) { + std::stringstream readValueStringStream; + readValueStringStream << (int) registers[addressOffset + this->parameterAddressOffset + i]; + readValueString.append(readValueStringStream.str().c_str()); + } + this->value.i = std::stoll(readValueString); +} + +std::string PortParameterInt::getOutputValue() { + return std::to_string(this->value.i).append(this->unit.c_str()); +} \ No newline at end of file diff --git a/src/hoymiles/src/sunspec.cpp b/src/hoymiles/src/sunspec.cpp new file mode 100644 index 0000000..d589477 --- /dev/null +++ b/src/hoymiles/src/sunspec.cpp @@ -0,0 +1,34 @@ +#include +#include +#include + +#include "sunspec.h" +#include "modbus.h" +#include "sunspecParameters.h" + +Sunspec::Sunspec(int address, modbus_t *modbus) { + this->modbus = modbus; + this->sunspecAddress = address; + + this->populateParameters(); + + this->setValues(); +} + +void Sunspec::setValues() { + uint16_t registers[2]; + + int registerCount; + registerCount = modbus_read_registers( this->modbus, this->sunspecAddress, 2, registers); + + std::vector>::iterator parametersIterator = this->parameters.begin(); + while(parametersIterator != this->parameters.end()) { + parametersIterator->get()->getValueFromRegisters(registers, 0); + parametersIterator++; + } +} + +void Sunspec::populateParameters() { + SunspecParameterManufacturer manufacturer{}; + this->parameters.push_back(std::make_shared(manufacturer)); +} \ No newline at end of file diff --git a/src/hoymiles/src/sunspecParameters/sunspecParameters.cpp b/src/hoymiles/src/sunspecParameters/sunspecParameters.cpp new file mode 100644 index 0000000..1b68bdd --- /dev/null +++ b/src/hoymiles/src/sunspecParameters/sunspecParameters.cpp @@ -0,0 +1,23 @@ +#include +#include +#include + +#include "sunspecParameters.h" + +SunspecParameterManufacturer::SunspecParameterManufacturer() : SunspecParameterString32("manufacturer", 4, 16) { + this->valueType = string32; +} + +void SunspecParameterManufacturer::getValueFromRegisters(uint16_t *registers, int addressOffset) { + std::string readValue; + + for(int i{0}; iregisterSize; i++) { + std::stringstream readValueStringStream; + readValueStringStream << (registers[addressOffset + this->registerAddressOffset + i] >> 8) << " "; + readValueStringStream << (registers[addressOffset + this->registerAddressOffset + i] & 0x00FF) << " "; + + readValue.append(readValueStringStream.str().c_str()); + } + + this->value = readValue; +} \ No newline at end of file diff --git a/src/hoymiles/src/sunspecParameters/sunspecParametersGeneric.cpp b/src/hoymiles/src/sunspecParameters/sunspecParametersGeneric.cpp new file mode 100644 index 0000000..93186e5 --- /dev/null +++ b/src/hoymiles/src/sunspecParameters/sunspecParametersGeneric.cpp @@ -0,0 +1,17 @@ +#include "sunspecParametersGeneric.h" + +SunspecParameter::~SunspecParameter() {} + +SunspecParameter::SunspecParameter(std::string name, int registerAddressOffset, int registerSize) { + this->name = name; + this->registerAddressOffset = registerAddressOffset; + this->registerSize = registerSize; +} + +void SunspecParameter::getValueFromRegisters(uint16_t *registers, int addressOffset) {} + +std::pair SunspecParameter::getValue() {} + +SunspecParameterString32::SunspecParameterString32(std::string name, int registerAddressOffset, int registerSize) : SunspecParameter(name, registerAddressOffset, registerSize) {} + +void SunspecParameterString32::getValueFromRegisters(uint16_t *registers, int addressOffset) {} \ No newline at end of file diff --git a/src/libmodbus/CMakeLists.txt b/src/libmodbus/CMakeLists.txt new file mode 100644 index 0000000..f5a42b3 --- /dev/null +++ b/src/libmodbus/CMakeLists.txt @@ -0,0 +1,7 @@ +include_directories(inc) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/inc/config.h) + +file(GLOB SOURCES src/*.c) + +add_library(libmodbus STATIC ${SOURCES}) \ No newline at end of file diff --git a/src/libmodbus/config.h.in b/src/libmodbus/config.h.in new file mode 100644 index 0000000..91492e8 --- /dev/null +++ b/src/libmodbus/config.h.in @@ -0,0 +1,291 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the `accept4' function. */ +#undef HAVE_ACCEPT4 + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_BYTESWAP_H + +/* Define to 1 if you have the declaration of `TIOCM_RTS', and to 0 if you + don't. */ +#undef HAVE_DECL_TIOCM_RTS + +/* Define to 1 if you have the declaration of `TIOCSRS485', and to 0 if you + don't. */ +#undef HAVE_DECL_TIOCSRS485 + +/* Define to 1 if you have the declaration of `__CYGWIN__', and to 0 if you + don't. */ +#undef HAVE_DECL___CYGWIN__ + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `getaddrinfo' function. */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the `inet_ntop' function. */ +#undef HAVE_INET_NTOP + +/* Define to 1 if you have the `inet_pton' function. */ +#undef HAVE_INET_PTON + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_SERIAL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MINIX_CONFIG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_TCP_H + +/* Define to 1 if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the `socket' function. */ +#undef HAVE_SOCKET + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAMS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WCHAR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINSOCK2_H + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ +#undef STDC_HEADERS + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable general extensions on macOS. */ +#ifndef _DARWIN_C_SOURCE +# undef _DARWIN_C_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable X/Open compliant socket functions that do not require linking + with -lxnet on HP-UX 11.11. */ +#ifndef _HPUX_ALT_XOPEN_SOCKET_API +# undef _HPUX_ALT_XOPEN_SOCKET_API +#endif +/* Identify the host operating system as Minix. + This macro does not affect the system headers' behavior. + A future release of Autoconf may stop defining this macro. */ +#ifndef _MINIX +# undef _MINIX +#endif +/* Enable general extensions on NetBSD. + Enable NetBSD compatibility extensions on Minix. */ +#ifndef _NETBSD_SOURCE +# undef _NETBSD_SOURCE +#endif +/* Enable OpenBSD compatibility extensions on NetBSD. + Oddly enough, this does nothing on OpenBSD. */ +#ifndef _OPENBSD_SOURCE +# undef _OPENBSD_SOURCE +#endif +/* Define to 1 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_SOURCE +# undef _POSIX_SOURCE +#endif +/* Define to 2 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_1_SOURCE +# undef _POSIX_1_SOURCE +#endif +/* Enable POSIX-compatible threading on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */ +#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ +# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */ +#ifndef __STDC_WANT_IEC_60559_BFP_EXT__ +# undef __STDC_WANT_IEC_60559_BFP_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */ +#ifndef __STDC_WANT_IEC_60559_DFP_EXT__ +# undef __STDC_WANT_IEC_60559_DFP_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */ +#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__ +# undef __STDC_WANT_IEC_60559_FUNCS_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */ +#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ +# undef __STDC_WANT_IEC_60559_TYPES_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */ +#ifndef __STDC_WANT_LIB_EXT2__ +# undef __STDC_WANT_LIB_EXT2__ +#endif +/* Enable extensions specified by ISO/IEC 24747:2009. */ +#ifndef __STDC_WANT_MATH_SPEC_FUNCS__ +# undef __STDC_WANT_MATH_SPEC_FUNCS__ +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable X/Open extensions. Define to 500 only if necessary + to make mbstate_t available. */ +#ifndef _XOPEN_SOURCE +# undef _XOPEN_SOURCE +#endif + + +/* Version number of package */ +#undef VERSION + +/* _ */ +#undef WINVER + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT32_T + +/* Define for Solaris 2.5.1 so the uint8_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT8_T + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to the type of a signed integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef int64_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to `int' if does not define. */ +#undef ssize_t + +/* Define to the type of an unsigned integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +#undef uint16_t + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef uint32_t + +/* Define to the type of an unsigned integer type of width exactly 8 bits if + such a type exists and the standard includes do not define it. */ +#undef uint8_t diff --git a/src/libmodbus/inc/config.h b/src/libmodbus/inc/config.h new file mode 100644 index 0000000..91492e8 --- /dev/null +++ b/src/libmodbus/inc/config.h @@ -0,0 +1,291 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the `accept4' function. */ +#undef HAVE_ACCEPT4 + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_BYTESWAP_H + +/* Define to 1 if you have the declaration of `TIOCM_RTS', and to 0 if you + don't. */ +#undef HAVE_DECL_TIOCM_RTS + +/* Define to 1 if you have the declaration of `TIOCSRS485', and to 0 if you + don't. */ +#undef HAVE_DECL_TIOCSRS485 + +/* Define to 1 if you have the declaration of `__CYGWIN__', and to 0 if you + don't. */ +#undef HAVE_DECL___CYGWIN__ + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `getaddrinfo' function. */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the `inet_ntop' function. */ +#undef HAVE_INET_NTOP + +/* Define to 1 if you have the `inet_pton' function. */ +#undef HAVE_INET_PTON + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_SERIAL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MINIX_CONFIG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_TCP_H + +/* Define to 1 if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the `socket' function. */ +#undef HAVE_SOCKET + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAMS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WCHAR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINSOCK2_H + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ +#undef STDC_HEADERS + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable general extensions on macOS. */ +#ifndef _DARWIN_C_SOURCE +# undef _DARWIN_C_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable X/Open compliant socket functions that do not require linking + with -lxnet on HP-UX 11.11. */ +#ifndef _HPUX_ALT_XOPEN_SOCKET_API +# undef _HPUX_ALT_XOPEN_SOCKET_API +#endif +/* Identify the host operating system as Minix. + This macro does not affect the system headers' behavior. + A future release of Autoconf may stop defining this macro. */ +#ifndef _MINIX +# undef _MINIX +#endif +/* Enable general extensions on NetBSD. + Enable NetBSD compatibility extensions on Minix. */ +#ifndef _NETBSD_SOURCE +# undef _NETBSD_SOURCE +#endif +/* Enable OpenBSD compatibility extensions on NetBSD. + Oddly enough, this does nothing on OpenBSD. */ +#ifndef _OPENBSD_SOURCE +# undef _OPENBSD_SOURCE +#endif +/* Define to 1 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_SOURCE +# undef _POSIX_SOURCE +#endif +/* Define to 2 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_1_SOURCE +# undef _POSIX_1_SOURCE +#endif +/* Enable POSIX-compatible threading on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */ +#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ +# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */ +#ifndef __STDC_WANT_IEC_60559_BFP_EXT__ +# undef __STDC_WANT_IEC_60559_BFP_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */ +#ifndef __STDC_WANT_IEC_60559_DFP_EXT__ +# undef __STDC_WANT_IEC_60559_DFP_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */ +#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__ +# undef __STDC_WANT_IEC_60559_FUNCS_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */ +#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ +# undef __STDC_WANT_IEC_60559_TYPES_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */ +#ifndef __STDC_WANT_LIB_EXT2__ +# undef __STDC_WANT_LIB_EXT2__ +#endif +/* Enable extensions specified by ISO/IEC 24747:2009. */ +#ifndef __STDC_WANT_MATH_SPEC_FUNCS__ +# undef __STDC_WANT_MATH_SPEC_FUNCS__ +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable X/Open extensions. Define to 500 only if necessary + to make mbstate_t available. */ +#ifndef _XOPEN_SOURCE +# undef _XOPEN_SOURCE +#endif + + +/* Version number of package */ +#undef VERSION + +/* _ */ +#undef WINVER + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT32_T + +/* Define for Solaris 2.5.1 so the uint8_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT8_T + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to the type of a signed integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef int64_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to `int' if does not define. */ +#undef ssize_t + +/* Define to the type of an unsigned integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +#undef uint16_t + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef uint32_t + +/* Define to the type of an unsigned integer type of width exactly 8 bits if + such a type exists and the standard includes do not define it. */ +#undef uint8_t diff --git a/src/libmodbus/inc/modbus-private.h b/src/libmodbus/inc/modbus-private.h new file mode 100644 index 0000000..6cd3424 --- /dev/null +++ b/src/libmodbus/inc/modbus-private.h @@ -0,0 +1,121 @@ +/* + * Copyright © Stéphane Raimbault + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef MODBUS_PRIVATE_H +#define MODBUS_PRIVATE_H + +// clang-format off +#ifndef _MSC_VER +# include +# include +#else +# include "stdint.h" +# include +typedef int ssize_t; +#endif +// clang-format on +#include +#include + +#include "modbus.h" + +MODBUS_BEGIN_DECLS + +/* It's not really the minimal length (the real one is report slave ID + * in RTU (4 bytes)) but it's a convenient size to use in RTU or TCP + * communications to read many values or write a single one. + * Maximum between : + * - HEADER_LENGTH_TCP (7) + function (1) + address (2) + number (2) + * - HEADER_LENGTH_RTU (1) + function (1) + address (2) + number (2) + CRC (2) + */ +#define _MIN_REQ_LENGTH 12 + +#define _REPORT_SLAVE_ID 180 + +#define _MODBUS_EXCEPTION_RSP_LENGTH 5 + +/* Timeouts in microsecond (0.5 s) */ +#define _RESPONSE_TIMEOUT 500000 +#define _BYTE_TIMEOUT 500000 + +typedef enum { + _MODBUS_BACKEND_TYPE_RTU = 0, + _MODBUS_BACKEND_TYPE_TCP +} modbus_backend_type_t; + +/* + * ---------- Request Indication ---------- + * | Client | ---------------------->| Server | + * ---------- Confirmation Response ---------- + */ +typedef enum { + /* Request message on the server side */ + MSG_INDICATION, + /* Request message on the client side */ + MSG_CONFIRMATION +} msg_type_t; + +/* This structure reduces the number of params in functions and so + * optimizes the speed of execution (~ 37%). */ +typedef struct _sft { + int slave; + int function; + int t_id; +} sft_t; + +typedef struct _modbus_backend { + unsigned int backend_type; + unsigned int header_length; + unsigned int checksum_length; + unsigned int max_adu_length; + int (*set_slave)(modbus_t *ctx, int slave); + int (*build_request_basis)( + modbus_t *ctx, int function, int addr, int nb, uint8_t *req); + int (*build_response_basis)(sft_t *sft, uint8_t *rsp); + int (*prepare_response_tid)(const uint8_t *req, int *req_length); + int (*send_msg_pre)(uint8_t *req, int req_length); + ssize_t (*send)(modbus_t *ctx, const uint8_t *req, int req_length); + int (*receive)(modbus_t *ctx, uint8_t *req); + ssize_t (*recv)(modbus_t *ctx, uint8_t *rsp, int rsp_length); + int (*check_integrity)(modbus_t *ctx, uint8_t *msg, const int msg_length); + int (*pre_check_confirmation)(modbus_t *ctx, + const uint8_t *req, + const uint8_t *rsp, + int rsp_length); + int (*connect)(modbus_t *ctx); + unsigned int (*is_connected)(modbus_t *ctx); + void (*close)(modbus_t *ctx); + int (*flush)(modbus_t *ctx); + int (*select)(modbus_t *ctx, fd_set *rset, struct timeval *tv, int msg_length); + void (*free)(modbus_t *ctx); +} modbus_backend_t; + +struct _modbus { + /* Slave address */ + int slave; + /* Socket or file descriptor */ + int s; + int debug; + int error_recovery; + int quirks; + struct timeval response_timeout; + struct timeval byte_timeout; + struct timeval indication_timeout; + const modbus_backend_t *backend; + void *backend_data; +}; + +void _modbus_init_common(modbus_t *ctx); +void _error_print(modbus_t *ctx, const char *context); +int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type); + +#ifndef HAVE_STRLCPY +size_t strlcpy(char *dest, const char *src, size_t dest_size); +#endif + +MODBUS_END_DECLS + +#endif /* MODBUS_PRIVATE_H */ diff --git a/src/libmodbus/inc/modbus-rtu-private.h b/src/libmodbus/inc/modbus-rtu-private.h new file mode 100644 index 0000000..01e6a91 --- /dev/null +++ b/src/libmodbus/inc/modbus-rtu-private.h @@ -0,0 +1,77 @@ +/* + * Copyright © Stéphane Raimbault + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef MODBUS_RTU_PRIVATE_H +#define MODBUS_RTU_PRIVATE_H + +#ifndef _MSC_VER +#include +#else +#include "stdint.h" +#endif + +#if defined(_WIN32) +#include +#else +#include +#endif + +#define _MODBUS_RTU_HEADER_LENGTH 1 +#define _MODBUS_RTU_PRESET_REQ_LENGTH 6 +#define _MODBUS_RTU_PRESET_RSP_LENGTH 2 + +#define _MODBUS_RTU_CHECKSUM_LENGTH 2 + +#if defined(_WIN32) +#if !defined(ENOTSUP) +#define ENOTSUP WSAEOPNOTSUPP +#endif + +/* WIN32: struct containing serial handle and a receive buffer */ +#define PY_BUF_SIZE 512 + +struct win32_ser { + /* File handle */ + HANDLE fd; + /* Receive buffer */ + uint8_t buf[PY_BUF_SIZE]; + /* Received chars */ + DWORD n_bytes; +}; +#endif /* _WIN32 */ + +typedef struct _modbus_rtu { + /* Device: "/dev/ttyS0", "/dev/ttyUSB0" or "/dev/tty.USA19*" on Mac OS X. */ + char *device; + /* Bauds: 9600, 19200, 57600, 115200, etc */ + int baud; + /* Data bit */ + uint8_t data_bit; + /* Stop bit */ + uint8_t stop_bit; + /* Parity: 'N', 'O', 'E' */ + char parity; +#if defined(_WIN32) + struct win32_ser w_ser; + DCB old_dcb; +#else + /* Save old termios settings */ + struct termios old_tios; +#endif +#if HAVE_DECL_TIOCSRS485 + int serial_mode; +#endif +#if HAVE_DECL_TIOCM_RTS + int rts; + int rts_delay; + int onebyte_time; + void (*set_rts)(modbus_t *ctx, int on); +#endif + /* To handle many slaves on the same link */ + int confirmation_to_ignore; +} modbus_rtu_t; + +#endif /* MODBUS_RTU_PRIVATE_H */ diff --git a/src/libmodbus/inc/modbus-rtu.h b/src/libmodbus/inc/modbus-rtu.h new file mode 100644 index 0000000..8e89e73 --- /dev/null +++ b/src/libmodbus/inc/modbus-rtu.h @@ -0,0 +1,43 @@ +/* + * Copyright © Stéphane Raimbault + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef MODBUS_RTU_H +#define MODBUS_RTU_H + +#include "modbus.h" + +MODBUS_BEGIN_DECLS + +/* Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5 + * RS232 / RS485 ADU = 253 bytes + slave (1 byte) + CRC (2 bytes) = 256 bytes + */ +#define MODBUS_RTU_MAX_ADU_LENGTH 256 + +MODBUS_API modbus_t * +modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit); + +#define MODBUS_RTU_RS232 0 +#define MODBUS_RTU_RS485 1 + +MODBUS_API int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode); +MODBUS_API int modbus_rtu_get_serial_mode(modbus_t *ctx); + +#define MODBUS_RTU_RTS_NONE 0 +#define MODBUS_RTU_RTS_UP 1 +#define MODBUS_RTU_RTS_DOWN 2 + +MODBUS_API int modbus_rtu_set_rts(modbus_t *ctx, int mode); +MODBUS_API int modbus_rtu_get_rts(modbus_t *ctx); + +MODBUS_API int modbus_rtu_set_custom_rts(modbus_t *ctx, + void (*set_rts)(modbus_t *ctx, int on)); + +MODBUS_API int modbus_rtu_set_rts_delay(modbus_t *ctx, int us); +MODBUS_API int modbus_rtu_get_rts_delay(modbus_t *ctx); + +MODBUS_END_DECLS + +#endif /* MODBUS_RTU_H */ diff --git a/src/libmodbus/inc/modbus-tcp-private.h b/src/libmodbus/inc/modbus-tcp-private.h new file mode 100644 index 0000000..faffc21 --- /dev/null +++ b/src/libmodbus/inc/modbus-tcp-private.h @@ -0,0 +1,41 @@ +/* + * Copyright © Stéphane Raimbault + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef MODBUS_TCP_PRIVATE_H +#define MODBUS_TCP_PRIVATE_H + +#define _MODBUS_TCP_HEADER_LENGTH 7 +#define _MODBUS_TCP_PRESET_REQ_LENGTH 12 +#define _MODBUS_TCP_PRESET_RSP_LENGTH 8 + +#define _MODBUS_TCP_CHECKSUM_LENGTH 0 + +/* In both structures, the transaction ID must be placed on first position + to have a quick access not dependent of the TCP backend */ +typedef struct _modbus_tcp { + /* Extract from MODBUS Messaging on TCP/IP Implementation Guide V1.0b + (page 23/46): + The transaction identifier is used to associate the future response + with the request. This identifier is unique on each TCP connection. */ + uint16_t t_id; + /* TCP port */ + int port; + /* IP address */ + char ip[16]; +} modbus_tcp_t; + +typedef struct _modbus_tcp_pi { + /* Transaction ID */ + uint16_t t_id; + /* TCP port */ + int port; + /* Node */ + char *node; + /* Service */ + char *service; +} modbus_tcp_pi_t; + +#endif /* MODBUS_TCP_PRIVATE_H */ diff --git a/src/libmodbus/inc/modbus-tcp.h b/src/libmodbus/inc/modbus-tcp.h new file mode 100644 index 0000000..768d38c --- /dev/null +++ b/src/libmodbus/inc/modbus-tcp.h @@ -0,0 +1,52 @@ +/* + * Copyright © Stéphane Raimbault + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef MODBUS_TCP_H +#define MODBUS_TCP_H + +#include "modbus.h" + +MODBUS_BEGIN_DECLS + +#if defined(_WIN32) && !defined(__CYGWIN__) +/* Win32 with MinGW, supplement to */ +#include +#if !defined(ECONNRESET) +#define ECONNRESET WSAECONNRESET +#endif +#if !defined(ECONNREFUSED) +#define ECONNREFUSED WSAECONNREFUSED +#endif +#if !defined(ETIMEDOUT) +#define ETIMEDOUT WSAETIMEDOUT +#endif +#if !defined(ENOPROTOOPT) +#define ENOPROTOOPT WSAENOPROTOOPT +#endif +#if !defined(EINPROGRESS) +#define EINPROGRESS WSAEINPROGRESS +#endif +#endif + +#define MODBUS_TCP_DEFAULT_PORT 502 +#define MODBUS_TCP_SLAVE 0xFF + +/* Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5 + * TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes + */ +#define MODBUS_TCP_MAX_ADU_LENGTH 260 + +MODBUS_API modbus_t *modbus_new_tcp(const char *ip_address, int port); +MODBUS_API int modbus_tcp_listen(modbus_t *ctx, int nb_connection); +MODBUS_API int modbus_tcp_accept(modbus_t *ctx, int *s); + +MODBUS_API modbus_t *modbus_new_tcp_pi(const char *node, const char *service); +MODBUS_API int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection); +MODBUS_API int modbus_tcp_pi_accept(modbus_t *ctx, int *s); + +MODBUS_END_DECLS + +#endif /* MODBUS_TCP_H */ diff --git a/src/libmodbus/inc/modbus-version.h b/src/libmodbus/inc/modbus-version.h new file mode 100644 index 0000000..16a34da --- /dev/null +++ b/src/libmodbus/inc/modbus-version.h @@ -0,0 +1,51 @@ +/* + * Copyright © Stéphane Raimbault + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MODBUS_VERSION_H +#define MODBUS_VERSION_H + +/* The major version, (1, if %LIBMODBUS_VERSION is 1.2.3) */ +#define LIBMODBUS_VERSION_MAJOR (3) + +/* The minor version (2, if %LIBMODBUS_VERSION is 1.2.3) */ +#define LIBMODBUS_VERSION_MINOR (1) + +/* The micro version (3, if %LIBMODBUS_VERSION is 1.2.3) */ +#define LIBMODBUS_VERSION_MICRO (10) + +/* The full version, like 1.2.3 */ +#define LIBMODBUS_VERSION 3.1.10 + +/* The full version, in string form (suited for string concatenation) + */ +#define LIBMODBUS_VERSION_STRING "3.1.10" + +/* Numerically encoded version, eg. v1.2.3 is 0x010203 */ +#define LIBMODBUS_VERSION_HEX \ + ((LIBMODBUS_VERSION_MAJOR << 16) | (LIBMODBUS_VERSION_MINOR << 8) | \ + (LIBMODBUS_VERSION_MICRO << 0)) + +/* Evaluates to True if the version is greater than @major, @minor and @micro + */ +#define LIBMODBUS_VERSION_CHECK(major, minor, micro) \ + (LIBMODBUS_VERSION_MAJOR > (major) || \ + (LIBMODBUS_VERSION_MAJOR == (major) && LIBMODBUS_VERSION_MINOR > (minor)) || \ + (LIBMODBUS_VERSION_MAJOR == (major) && LIBMODBUS_VERSION_MINOR == (minor) && \ + LIBMODBUS_VERSION_MICRO >= (micro))) + +#endif /* MODBUS_VERSION_H */ diff --git a/src/libmodbus/inc/modbus.h b/src/libmodbus/inc/modbus.h new file mode 100644 index 0000000..55ef08a --- /dev/null +++ b/src/libmodbus/inc/modbus.h @@ -0,0 +1,329 @@ +/* + * Copyright © Stéphane Raimbault + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef MODBUS_H +#define MODBUS_H + +// clang-format off +/* Add this for macros that defined unix flavor */ +#if (defined(__unix__) || defined(unix)) && !defined(USG) +# include +#endif + +#ifndef _MSC_VER +# include +#else +# include "stdint.h" +#endif + +#include "modbus-version.h" + +#if defined(_MSC_VER) +# if defined(DLLBUILD) +/* define DLLBUILD when building the DLL */ +# define MODBUS_API __declspec(dllexport) +# else +# define MODBUS_API __declspec(dllimport) +# endif +#else +# define MODBUS_API +#endif + +#ifdef __cplusplus +# define MODBUS_BEGIN_DECLS extern "C" { +# define MODBUS_END_DECLS } +#else +# define MODBUS_BEGIN_DECLS +# define MODBUS_END_DECLS +#endif +// clang-format on + +MODBUS_BEGIN_DECLS + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef OFF +#define OFF 0 +#endif + +#ifndef ON +#define ON 1 +#endif + +/* Modbus function codes */ +#define MODBUS_FC_READ_COILS 0x01 +#define MODBUS_FC_READ_DISCRETE_INPUTS 0x02 +#define MODBUS_FC_READ_HOLDING_REGISTERS 0x03 +#define MODBUS_FC_READ_INPUT_REGISTERS 0x04 +#define MODBUS_FC_WRITE_SINGLE_COIL 0x05 +#define MODBUS_FC_WRITE_SINGLE_REGISTER 0x06 +#define MODBUS_FC_READ_EXCEPTION_STATUS 0x07 +#define MODBUS_FC_WRITE_MULTIPLE_COILS 0x0F +#define MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10 +#define MODBUS_FC_REPORT_SLAVE_ID 0x11 +#define MODBUS_FC_MASK_WRITE_REGISTER 0x16 +#define MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17 + +#define MODBUS_BROADCAST_ADDRESS 0 + +/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 1 page 12) + * Quantity of Coils to read (2 bytes): 1 to 2000 (0x7D0) + * (chapter 6 section 11 page 29) + * Quantity of Coils to write (2 bytes): 1 to 1968 (0x7B0) + */ +#define MODBUS_MAX_READ_BITS 2000 +#define MODBUS_MAX_WRITE_BITS 1968 + +/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 3 page 15) + * Quantity of Registers to read (2 bytes): 1 to 125 (0x7D) + * (chapter 6 section 12 page 31) + * Quantity of Registers to write (2 bytes) 1 to 123 (0x7B) + * (chapter 6 section 17 page 38) + * Quantity of Registers to write in R/W registers (2 bytes) 1 to 121 (0x79) + */ +#define MODBUS_MAX_READ_REGISTERS 125 +#define MODBUS_MAX_WRITE_REGISTERS 123 +#define MODBUS_MAX_WR_WRITE_REGISTERS 121 +#define MODBUS_MAX_WR_READ_REGISTERS 125 + +/* The size of the MODBUS PDU is limited by the size constraint inherited from + * the first MODBUS implementation on Serial Line network (max. RS485 ADU = 256 + * bytes). Therefore, MODBUS PDU for serial line communication = 256 - Server + * address (1 byte) - CRC (2 bytes) = 253 bytes. + */ +#define MODBUS_MAX_PDU_LENGTH 253 + +/* Consequently: + * - RTU MODBUS ADU = 253 bytes + Server address (1 byte) + CRC (2 bytes) = 256 + * bytes. + * - TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes. + * so the maximum of both backend in 260 bytes. This size can used to allocate + * an array of bytes to store responses and it will be compatible with the two + * backends. + */ +#define MODBUS_MAX_ADU_LENGTH 260 + +/* Random number to avoid errno conflicts */ +#define MODBUS_ENOBASE 112345678 + +/* Protocol exceptions */ +enum { + MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 0x01, + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, + MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE, + MODBUS_EXCEPTION_ACKNOWLEDGE, + MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY, + MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE, + MODBUS_EXCEPTION_MEMORY_PARITY, + MODBUS_EXCEPTION_NOT_DEFINED, + MODBUS_EXCEPTION_GATEWAY_PATH, + MODBUS_EXCEPTION_GATEWAY_TARGET, + MODBUS_EXCEPTION_MAX +}; + +#define EMBXILFUN (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_FUNCTION) +#define EMBXILADD (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS) +#define EMBXILVAL (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE) +#define EMBXSFAIL (MODBUS_ENOBASE + MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE) +#define EMBXACK (MODBUS_ENOBASE + MODBUS_EXCEPTION_ACKNOWLEDGE) +#define EMBXSBUSY (MODBUS_ENOBASE + MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY) +#define EMBXNACK (MODBUS_ENOBASE + MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE) +#define EMBXMEMPAR (MODBUS_ENOBASE + MODBUS_EXCEPTION_MEMORY_PARITY) +#define EMBXGPATH (MODBUS_ENOBASE + MODBUS_EXCEPTION_GATEWAY_PATH) +#define EMBXGTAR (MODBUS_ENOBASE + MODBUS_EXCEPTION_GATEWAY_TARGET) + +/* Native libmodbus error codes */ +#define EMBBADCRC (EMBXGTAR + 1) +#define EMBBADDATA (EMBXGTAR + 2) +#define EMBBADEXC (EMBXGTAR + 3) +#define EMBUNKEXC (EMBXGTAR + 4) +#define EMBMDATA (EMBXGTAR + 5) +#define EMBBADSLAVE (EMBXGTAR + 6) + +extern const unsigned int libmodbus_version_major; +extern const unsigned int libmodbus_version_minor; +extern const unsigned int libmodbus_version_micro; + +typedef struct _modbus modbus_t; + +typedef struct _modbus_mapping_t { + int nb_bits; + int start_bits; + int nb_input_bits; + int start_input_bits; + int nb_input_registers; + int start_input_registers; + int nb_registers; + int start_registers; + uint8_t *tab_bits; + uint8_t *tab_input_bits; + uint16_t *tab_input_registers; + uint16_t *tab_registers; +} modbus_mapping_t; + +typedef enum { + MODBUS_ERROR_RECOVERY_NONE = 0, + MODBUS_ERROR_RECOVERY_LINK = (1 << 1), + MODBUS_ERROR_RECOVERY_PROTOCOL = (1 << 2) +} modbus_error_recovery_mode; + +typedef enum { + MODBUS_QUIRK_NONE = 0, + MODBUS_QUIRK_MAX_SLAVE = (1 << 1), + MODBUS_QUIRK_REPLY_TO_BROADCAST = (1 << 2), + MODBUS_QUIRK_ALL = 0xFF +} modbus_quirks; + +MODBUS_API int modbus_set_slave(modbus_t *ctx, int slave); +MODBUS_API int modbus_get_slave(modbus_t *ctx); +MODBUS_API int modbus_set_error_recovery(modbus_t *ctx, + modbus_error_recovery_mode error_recovery); +MODBUS_API int modbus_set_socket(modbus_t *ctx, int s); +MODBUS_API int modbus_get_socket(modbus_t *ctx); + +MODBUS_API int +modbus_get_response_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec); +MODBUS_API int +modbus_set_response_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec); + +MODBUS_API int +modbus_get_byte_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec); +MODBUS_API int modbus_set_byte_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec); + +MODBUS_API int +modbus_get_indication_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec); +MODBUS_API int +modbus_set_indication_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec); + +MODBUS_API int modbus_get_header_length(modbus_t *ctx); + +MODBUS_API int modbus_connect(modbus_t *ctx); +MODBUS_API void modbus_close(modbus_t *ctx); + +MODBUS_API void modbus_free(modbus_t *ctx); + +MODBUS_API int modbus_flush(modbus_t *ctx); +MODBUS_API int modbus_set_debug(modbus_t *ctx, int flag); + +MODBUS_API const char *modbus_strerror(int errnum); + +MODBUS_API int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest); +MODBUS_API int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest); +MODBUS_API int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest); +MODBUS_API int +modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest); +MODBUS_API int modbus_write_bit(modbus_t *ctx, int coil_addr, int status); +MODBUS_API int modbus_write_register(modbus_t *ctx, int reg_addr, const uint16_t value); +MODBUS_API int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *data); +MODBUS_API int +modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *data); +MODBUS_API int +modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask); +MODBUS_API int modbus_write_and_read_registers(modbus_t *ctx, + int write_addr, + int write_nb, + const uint16_t *src, + int read_addr, + int read_nb, + uint16_t *dest); +MODBUS_API int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest); + +MODBUS_API modbus_mapping_t * +modbus_mapping_new_start_address(unsigned int start_bits, + unsigned int nb_bits, + unsigned int start_input_bits, + unsigned int nb_input_bits, + unsigned int start_registers, + unsigned int nb_registers, + unsigned int start_input_registers, + unsigned int nb_input_registers); + +MODBUS_API modbus_mapping_t *modbus_mapping_new(int nb_bits, + int nb_input_bits, + int nb_registers, + int nb_input_registers); +MODBUS_API void modbus_mapping_free(modbus_mapping_t *mb_mapping); + +MODBUS_API int +modbus_send_raw_request(modbus_t *ctx, const uint8_t *raw_req, int raw_req_length); + +MODBUS_API int modbus_receive(modbus_t *ctx, uint8_t *req); + +MODBUS_API int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp); + +MODBUS_API int modbus_reply(modbus_t *ctx, + const uint8_t *req, + int req_length, + modbus_mapping_t *mb_mapping); +MODBUS_API int +modbus_reply_exception(modbus_t *ctx, const uint8_t *req, unsigned int exception_code); +MODBUS_API int modbus_enable_quirks(modbus_t *ctx, unsigned int quirks_mask); +MODBUS_API int modbus_disable_quirks(modbus_t *ctx, unsigned int quirks_mask); + +/** + * UTILS FUNCTIONS + **/ + +#define MODBUS_GET_HIGH_BYTE(data) (((data) >> 8) & 0xFF) +#define MODBUS_GET_LOW_BYTE(data) ((data) &0xFF) +#define MODBUS_GET_INT64_FROM_INT16(tab_int16, index) \ + (((int64_t) tab_int16[(index)] << 48) | ((int64_t) tab_int16[(index) + 1] << 32) | \ + ((int64_t) tab_int16[(index) + 2] << 16) | (int64_t) tab_int16[(index) + 3]) +#define MODBUS_GET_INT32_FROM_INT16(tab_int16, index) \ + (((int32_t) tab_int16[(index)] << 16) | (int32_t) tab_int16[(index) + 1]) +#define MODBUS_GET_INT16_FROM_INT8(tab_int8, index) \ + (((int16_t) tab_int8[(index)] << 8) | (int16_t) tab_int8[(index) + 1]) +#define MODBUS_SET_INT16_TO_INT8(tab_int8, index, value) \ + do { \ + ((int8_t *) (tab_int8))[(index)] = (int8_t) ((value) >> 8); \ + ((int8_t *) (tab_int8))[(index) + 1] = (int8_t) (value); \ + } while (0) +#define MODBUS_SET_INT32_TO_INT16(tab_int16, index, value) \ + do { \ + ((int16_t *) (tab_int16))[(index)] = (int16_t) ((value) >> 16); \ + ((int16_t *) (tab_int16))[(index) + 1] = (int16_t) (value); \ + } while (0) +#define MODBUS_SET_INT64_TO_INT16(tab_int16, index, value) \ + do { \ + ((int16_t *) (tab_int16))[(index)] = (int16_t) ((value) >> 48); \ + ((int16_t *) (tab_int16))[(index) + 1] = (int16_t) ((value) >> 32); \ + ((int16_t *) (tab_int16))[(index) + 2] = (int16_t) ((value) >> 16); \ + ((int16_t *) (tab_int16))[(index) + 3] = (int16_t) (value); \ + } while (0) + +MODBUS_API void modbus_set_bits_from_byte(uint8_t *dest, int idx, const uint8_t value); +MODBUS_API void modbus_set_bits_from_bytes(uint8_t *dest, + int idx, + unsigned int nb_bits, + const uint8_t *tab_byte); +MODBUS_API uint8_t modbus_get_byte_from_bits(const uint8_t *src, + int idx, + unsigned int nb_bits); +MODBUS_API float modbus_get_float(const uint16_t *src); +MODBUS_API float modbus_get_float_abcd(const uint16_t *src); +MODBUS_API float modbus_get_float_dcba(const uint16_t *src); +MODBUS_API float modbus_get_float_badc(const uint16_t *src); +MODBUS_API float modbus_get_float_cdab(const uint16_t *src); + +MODBUS_API void modbus_set_float(float f, uint16_t *dest); +MODBUS_API void modbus_set_float_abcd(float f, uint16_t *dest); +MODBUS_API void modbus_set_float_dcba(float f, uint16_t *dest); +MODBUS_API void modbus_set_float_badc(float f, uint16_t *dest); +MODBUS_API void modbus_set_float_cdab(float f, uint16_t *dest); + +#include "modbus-rtu.h" +#include "modbus-tcp.h" + +MODBUS_END_DECLS + +#endif /* MODBUS_H */ diff --git a/src/libmodbus/src/modbus-data.c b/src/libmodbus/src/modbus-data.c new file mode 100644 index 0000000..8aeef0c --- /dev/null +++ b/src/libmodbus/src/modbus-data.c @@ -0,0 +1,292 @@ +/* + * Copyright © Stéphane Raimbault + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include + +// clang-format off +#ifndef _MSC_VER +# include +#else +# include "stdint.h" +#endif + +#include +#include + +#if defined(_WIN32) +# include +#else +# include +#endif + +#include + +#include "modbus.h" + +#if defined(HAVE_BYTESWAP_H) +# include +#endif + +#if defined(__APPLE__) +# include +# define bswap_16 OSSwapInt16 +# define bswap_32 OSSwapInt32 +# define bswap_64 OSSwapInt64 +#endif + +#if defined(__GNUC__) +# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__ * 10) +# if GCC_VERSION >= 430 +// Since GCC >= 4.30, GCC provides __builtin_bswapXX() alternatives so we switch to them +# undef bswap_32 +# define bswap_32 __builtin_bswap32 +# endif +# if GCC_VERSION >= 480 +# undef bswap_16 +# define bswap_16 __builtin_bswap16 +# endif +#endif + +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +# define bswap_32 _byteswap_ulong +# define bswap_16 _byteswap_ushort +#endif + +#if !defined(bswap_16) +# warning "Fallback on C functions for bswap_16" +static inline uint16_t bswap_16(uint16_t x) +{ + return (x >> 8) | (x << 8); +} +#endif + +#if !defined(bswap_32) +# warning "Fallback on C functions for bswap_32" +static inline uint32_t bswap_32(uint32_t x) +{ + return (bswap_16(x & 0xffff) << 16) | (bswap_16(x >> 16)); +} +#endif +// clang-format on + +/* Sets many bits from a single byte value (all 8 bits of the byte value are + set) */ +void modbus_set_bits_from_byte(uint8_t *dest, int idx, const uint8_t value) +{ + int i; + + for (i = 0; i < 8; i++) { + dest[idx + i] = (value & (1 << i)) ? 1 : 0; + } +} + +/* Sets many bits from a table of bytes (only the bits between idx and + idx + nb_bits are set) */ +void modbus_set_bits_from_bytes(uint8_t *dest, + int idx, + unsigned int nb_bits, + const uint8_t *tab_byte) +{ + unsigned int i; + int shift = 0; + + for (i = idx; i < idx + nb_bits; i++) { + dest[i] = tab_byte[(i - idx) / 8] & (1 << shift) ? 1 : 0; + /* gcc doesn't like: shift = (++shift) % 8; */ + shift++; + shift %= 8; + } +} + +/* Gets the byte value from many bits. + To obtain a full byte, set nb_bits to 8. */ +uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx, unsigned int nb_bits) +{ + unsigned int i; + uint8_t value = 0; + + if (nb_bits > 8) { + /* Assert is ignored if NDEBUG is set */ + assert(nb_bits < 8); + nb_bits = 8; + } + + for (i = 0; i < nb_bits; i++) { + value |= (src[idx + i] << i); + } + + return value; +} + +/* Get a float from 4 bytes (Modbus) without any conversion (ABCD) */ +float modbus_get_float_abcd(const uint16_t *src) +{ + float f; + uint32_t i; + uint8_t a, b, c, d; + + a = (src[0] >> 8) & 0xFF; + b = (src[0] >> 0) & 0xFF; + c = (src[1] >> 8) & 0xFF; + d = (src[1] >> 0) & 0xFF; + + i = (a << 24) | (b << 16) | (c << 8) | (d << 0); + memcpy(&f, &i, 4); + + return f; +} + +/* Get a float from 4 bytes (Modbus) in inversed format (DCBA) */ +float modbus_get_float_dcba(const uint16_t *src) +{ + float f; + uint32_t i; + uint8_t a, b, c, d; + + a = (src[0] >> 8) & 0xFF; + b = (src[0] >> 0) & 0xFF; + c = (src[1] >> 8) & 0xFF; + d = (src[1] >> 0) & 0xFF; + + i = (d << 24) | (c << 16) | (b << 8) | (a << 0); + memcpy(&f, &i, 4); + + return f; +} + +/* Get a float from 4 bytes (Modbus) with swapped bytes (BADC) */ +float modbus_get_float_badc(const uint16_t *src) +{ + float f; + uint32_t i; + uint8_t a, b, c, d; + + a = (src[0] >> 8) & 0xFF; + b = (src[0] >> 0) & 0xFF; + c = (src[1] >> 8) & 0xFF; + d = (src[1] >> 0) & 0xFF; + + i = (b << 24) | (a << 16) | (d << 8) | (c << 0); + memcpy(&f, &i, 4); + + return f; +} + +/* Get a float from 4 bytes (Modbus) with swapped words (CDAB) */ +float modbus_get_float_cdab(const uint16_t *src) +{ + float f; + uint32_t i; + uint8_t a, b, c, d; + + a = (src[0] >> 8) & 0xFF; + b = (src[0] >> 0) & 0xFF; + c = (src[1] >> 8) & 0xFF; + d = (src[1] >> 0) & 0xFF; + + i = (c << 24) | (d << 16) | (a << 8) | (b << 0); + memcpy(&f, &i, 4); + + return f; +} + +/* DEPRECATED - Get a float from 4 bytes in sort of Modbus format */ +float modbus_get_float(const uint16_t *src) +{ + float f; + uint32_t i; + + i = (((uint32_t) src[1]) << 16) + src[0]; + memcpy(&f, &i, sizeof(float)); + + return f; +} + +/* Set a float to 4 bytes for Modbus w/o any conversion (ABCD) */ +void modbus_set_float_abcd(float f, uint16_t *dest) +{ + uint32_t i; + uint8_t *out = (uint8_t *) dest; + uint8_t a, b, c, d; + + memcpy(&i, &f, sizeof(uint32_t)); + a = (i >> 24) & 0xFF; + b = (i >> 16) & 0xFF; + c = (i >> 8) & 0xFF; + d = (i >> 0) & 0xFF; + + out[0] = a; + out[1] = b; + out[2] = c; + out[3] = d; +} + +/* Set a float to 4 bytes for Modbus with byte and word swap conversion (DCBA) */ +void modbus_set_float_dcba(float f, uint16_t *dest) +{ + uint32_t i; + uint8_t *out = (uint8_t *) dest; + uint8_t a, b, c, d; + + memcpy(&i, &f, sizeof(uint32_t)); + a = (i >> 24) & 0xFF; + b = (i >> 16) & 0xFF; + c = (i >> 8) & 0xFF; + d = (i >> 0) & 0xFF; + + out[0] = d; + out[1] = c; + out[2] = b; + out[3] = a; +} + +/* Set a float to 4 bytes for Modbus with byte swap conversion (BADC) */ +void modbus_set_float_badc(float f, uint16_t *dest) +{ + uint32_t i; + uint8_t *out = (uint8_t *) dest; + uint8_t a, b, c, d; + + memcpy(&i, &f, sizeof(uint32_t)); + a = (i >> 24) & 0xFF; + b = (i >> 16) & 0xFF; + c = (i >> 8) & 0xFF; + d = (i >> 0) & 0xFF; + + out[0] = b; + out[1] = a; + out[2] = d; + out[3] = c; +} + +/* Set a float to 4 bytes for Modbus with word swap conversion (CDAB) */ +void modbus_set_float_cdab(float f, uint16_t *dest) +{ + uint32_t i; + uint8_t *out = (uint8_t *) dest; + uint8_t a, b, c, d; + + memcpy(&i, &f, sizeof(uint32_t)); + a = (i >> 24) & 0xFF; + b = (i >> 16) & 0xFF; + c = (i >> 8) & 0xFF; + d = (i >> 0) & 0xFF; + + out[0] = c; + out[1] = d; + out[2] = a; + out[3] = b; +} + +/* DEPRECATED - Set a float to 4 bytes in a sort of Modbus format! */ +void modbus_set_float(float f, uint16_t *dest) +{ + uint32_t i; + + memcpy(&i, &f, sizeof(uint32_t)); + dest[0] = (uint16_t) i; + dest[1] = (uint16_t) (i >> 16); +} diff --git a/src/libmodbus/src/modbus-rtu.c b/src/libmodbus/src/modbus-rtu.c new file mode 100644 index 0000000..b774923 --- /dev/null +++ b/src/libmodbus/src/modbus-rtu.c @@ -0,0 +1,1290 @@ +/* + * Copyright © Stéphane Raimbault + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include +#include +#include +#include +#include +#ifndef _MSC_VER +#include +#endif +#include "modbus-private.h" +#include + +#include "modbus-rtu-private.h" +#include "modbus-rtu.h" + +#if HAVE_DECL_TIOCSRS485 || HAVE_DECL_TIOCM_RTS +#include +#endif + +#if HAVE_DECL_TIOCSRS485 +#include +#endif + +/* Table of CRC values for high-order byte */ +static const uint8_t table_crc_hi[] = { + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, + 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, + 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, + 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, + 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, + 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, + 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, + 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, + 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, + 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40}; + +/* Table of CRC values for low-order byte */ +static const uint8_t table_crc_lo[] = { + 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, + 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, + 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, + 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, + 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, + 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, + 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, + 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, + 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, + 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, + 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, + 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, + 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, + 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, + 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, + 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, + 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, + 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, + 0x41, 0x81, 0x80, 0x40}; + +/* Define the slave ID of the remote device to talk in master mode or set the + * internal slave ID in slave mode */ +static int _modbus_set_slave(modbus_t *ctx, int slave) +{ + int max_slave = (ctx->quirks & MODBUS_QUIRK_MAX_SLAVE) ? 255 : 247; + + /* Broadcast address is 0 (MODBUS_BROADCAST_ADDRESS) */ + if (slave >= 0 && slave <= max_slave) { + ctx->slave = slave; + } else { + errno = EINVAL; + return -1; + } + + return 0; +} + +/* Builds a RTU request header */ +static int _modbus_rtu_build_request_basis( + modbus_t *ctx, int function, int addr, int nb, uint8_t *req) +{ + assert(ctx->slave != -1); + req[0] = ctx->slave; + req[1] = function; + req[2] = addr >> 8; + req[3] = addr & 0x00ff; + req[4] = nb >> 8; + req[5] = nb & 0x00ff; + + return _MODBUS_RTU_PRESET_REQ_LENGTH; +} + +/* Builds a RTU response header */ +static int _modbus_rtu_build_response_basis(sft_t *sft, uint8_t *rsp) +{ + /* In this case, the slave is certainly valid because a check is already + * done in _modbus_rtu_listen */ + rsp[0] = sft->slave; + rsp[1] = sft->function; + + return _MODBUS_RTU_PRESET_RSP_LENGTH; +} + +static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length) +{ + uint8_t crc_hi = 0xFF; /* high CRC byte initialized */ + uint8_t crc_lo = 0xFF; /* low CRC byte initialized */ + unsigned int i; /* will index into CRC lookup */ + + /* pass through message buffer */ + while (buffer_length--) { + i = crc_lo ^ *buffer++; /* calculate the CRC */ + crc_lo = crc_hi ^ table_crc_hi[i]; + crc_hi = table_crc_lo[i]; + } + + return (crc_hi << 8 | crc_lo); +} + +static int _modbus_rtu_prepare_response_tid(const uint8_t *req, int *req_length) +{ + (*req_length) -= _MODBUS_RTU_CHECKSUM_LENGTH; + /* No TID */ + return 0; +} + +static int _modbus_rtu_send_msg_pre(uint8_t *req, int req_length) +{ + uint16_t crc = crc16(req, req_length); + + /* According to the MODBUS specs (p. 14), the low order byte of the CRC comes + * first in the RTU message */ + req[req_length++] = crc & 0x00FF; + req[req_length++] = crc >> 8; + + return req_length; +} + +#if defined(_WIN32) + +/* This simple implementation is sort of a substitute of the select() call, + * working this way: the win32_ser_select() call tries to read some data from + * the serial port, setting the timeout as the select() call would. Data read is + * stored into the receive buffer, that is then consumed by the win32_ser_read() + * call. So win32_ser_select() does both the event waiting and the reading, + * while win32_ser_read() only consumes the receive buffer. + */ + +static void win32_ser_init(struct win32_ser *ws) +{ + /* Clear everything */ + memset(ws, 0x00, sizeof(struct win32_ser)); + + /* Set file handle to invalid */ + ws->fd = INVALID_HANDLE_VALUE; +} + +/* FIXME Try to remove length_to_read -> max_len argument, only used by win32 */ +static int win32_ser_select(struct win32_ser *ws, int max_len, const struct timeval *tv) +{ + COMMTIMEOUTS comm_to; + unsigned int msec = 0; + + /* Check if some data still in the buffer to be consumed */ + if (ws->n_bytes > 0) { + return 1; + } + + /* Setup timeouts like select() would do. + FIXME Please someone on Windows can look at this? + Does it possible to use WaitCommEvent? + When tv is NULL, MAXDWORD isn't infinite! + */ + if (tv == NULL) { + msec = MAXDWORD; + } else { + msec = tv->tv_sec * 1000 + tv->tv_usec / 1000; + if (msec < 1) + msec = 1; + } + + comm_to.ReadIntervalTimeout = msec; + comm_to.ReadTotalTimeoutMultiplier = 0; + comm_to.ReadTotalTimeoutConstant = msec; + comm_to.WriteTotalTimeoutMultiplier = 0; + comm_to.WriteTotalTimeoutConstant = 1000; + SetCommTimeouts(ws->fd, &comm_to); + + /* Read some bytes */ + if ((max_len > PY_BUF_SIZE) || (max_len < 0)) { + max_len = PY_BUF_SIZE; + } + + if (ReadFile(ws->fd, &ws->buf, max_len, &ws->n_bytes, NULL)) { + /* Check if some bytes available */ + if (ws->n_bytes > 0) { + /* Some bytes read */ + return 1; + } else { + /* Just timed out */ + return 0; + } + } else { + /* Some kind of error */ + return -1; + } +} + +static int win32_ser_read(struct win32_ser *ws, uint8_t *p_msg, unsigned int max_len) +{ + unsigned int n = ws->n_bytes; + + if (max_len < n) { + n = max_len; + } + + if (n > 0) { + memcpy(p_msg, ws->buf, n); + } + + ws->n_bytes -= n; + + return n; +} +#endif + +#if HAVE_DECL_TIOCM_RTS +static void _modbus_rtu_ioctl_rts(modbus_t *ctx, int on) +{ + int fd = ctx->s; + int flags; + + ioctl(fd, TIOCMGET, &flags); + if (on) { + flags |= TIOCM_RTS; + } else { + flags &= ~TIOCM_RTS; + } + ioctl(fd, TIOCMSET, &flags); +} +#endif + +static ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_length) +{ +#if defined(_WIN32) + modbus_rtu_t *ctx_rtu = ctx->backend_data; + DWORD n_bytes = 0; + return (WriteFile(ctx_rtu->w_ser.fd, req, req_length, &n_bytes, NULL)) + ? (ssize_t) n_bytes + : -1; +#else +#if HAVE_DECL_TIOCM_RTS + modbus_rtu_t *ctx_rtu = ctx->backend_data; + if (ctx_rtu->rts != MODBUS_RTU_RTS_NONE) { + ssize_t size; + + if (ctx->debug) { + fprintf(stderr, "Sending request using RTS signal\n"); + } + + ctx_rtu->set_rts(ctx, ctx_rtu->rts == MODBUS_RTU_RTS_UP); + usleep(ctx_rtu->rts_delay); + + size = write(ctx->s, req, req_length); + + usleep(ctx_rtu->onebyte_time * req_length + ctx_rtu->rts_delay); + ctx_rtu->set_rts(ctx, ctx_rtu->rts != MODBUS_RTU_RTS_UP); + + return size; + } else { +#endif + return write(ctx->s, req, req_length); +#if HAVE_DECL_TIOCM_RTS + } +#endif +#endif +} + +static int _modbus_rtu_receive(modbus_t *ctx, uint8_t *req) +{ + int rc; + modbus_rtu_t *ctx_rtu = ctx->backend_data; + + if (ctx_rtu->confirmation_to_ignore) { + _modbus_receive_msg(ctx, req, MSG_CONFIRMATION); + /* Ignore errors and reset the flag */ + ctx_rtu->confirmation_to_ignore = FALSE; + rc = 0; + if (ctx->debug) { + printf("Confirmation to ignore\n"); + } + } else { + rc = _modbus_receive_msg(ctx, req, MSG_INDICATION); + if (rc == 0) { + /* The next expected message is a confirmation to ignore */ + ctx_rtu->confirmation_to_ignore = TRUE; + } + } + return rc; +} + +static ssize_t _modbus_rtu_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length) +{ +#if defined(_WIN32) + return win32_ser_read(&((modbus_rtu_t *) ctx->backend_data)->w_ser, rsp, rsp_length); +#else + return read(ctx->s, rsp, rsp_length); +#endif +} + +static int _modbus_rtu_flush(modbus_t *); + +static int _modbus_rtu_pre_check_confirmation(modbus_t *ctx, + const uint8_t *req, + const uint8_t *rsp, + int rsp_length) +{ + /* Check responding slave is the slave we requested (except for broacast + * request) */ + if (req[0] != rsp[0] && req[0] != MODBUS_BROADCAST_ADDRESS) { + if (ctx->debug) { + fprintf(stderr, + "The responding slave %d isn't the requested slave %d\n", + rsp[0], + req[0]); + } + errno = EMBBADSLAVE; + return -1; + } else { + return 0; + } +} + +/* The check_crc16 function shall return 0 if the message is ignored and the + message length if the CRC is valid. Otherwise it shall return -1 and set + errno to EMBBADCRC. */ +static int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg, const int msg_length) +{ + uint16_t crc_calculated; + uint16_t crc_received; + int slave = msg[0]; + + /* Filter on the Modbus unit identifier (slave) in RTU mode to avoid useless + * CRC computing. */ + if (slave != ctx->slave && slave != MODBUS_BROADCAST_ADDRESS) { + if (ctx->debug) { + printf("Request for slave %d ignored (not %d)\n", slave, ctx->slave); + } + /* Following call to check_confirmation handles this error */ + return 0; + } + + crc_calculated = crc16(msg, msg_length - 2); + crc_received = (msg[msg_length - 1] << 8) | msg[msg_length - 2]; + + /* Check CRC of msg */ + if (crc_calculated == crc_received) { + return msg_length; + } else { + if (ctx->debug) { + fprintf(stderr, + "ERROR CRC received 0x%0X != CRC calculated 0x%0X\n", + crc_received, + crc_calculated); + } + + if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) { + _modbus_rtu_flush(ctx); + } + errno = EMBBADCRC; + return -1; + } +} + +/* Sets up a serial port for RTU communications */ +#if defined(_WIN32) +static int _modbus_rtu_connect(modbus_t *ctx) +{ + DCB dcb; + modbus_rtu_t *ctx_rtu = ctx->backend_data; + + if (ctx->debug) { + printf("Opening %s at %d bauds (%c, %d, %d)\n", + ctx_rtu->device, + ctx_rtu->baud, + ctx_rtu->parity, + ctx_rtu->data_bit, + ctx_rtu->stop_bit); + } + + /* Some references here: + * http://msdn.microsoft.com/en-us/library/aa450602.aspx + */ + win32_ser_init(&ctx_rtu->w_ser); + + /* ctx_rtu->device should contain a string like "COMxx:" xx being a decimal + * number */ + ctx_rtu->w_ser.fd = CreateFileA( + ctx_rtu->device, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + + /* Error checking */ + if (ctx_rtu->w_ser.fd == INVALID_HANDLE_VALUE) { + if (ctx->debug) { + fprintf(stderr, + "ERROR Can't open the device %s (LastError %d)\n", + ctx_rtu->device, + (int) GetLastError()); + } + return -1; + } + + /* Save params */ + ctx_rtu->old_dcb.DCBlength = sizeof(DCB); + if (!GetCommState(ctx_rtu->w_ser.fd, &ctx_rtu->old_dcb)) { + if (ctx->debug) { + fprintf(stderr, + "ERROR Error getting configuration (LastError %d)\n", + (int) GetLastError()); + } + CloseHandle(ctx_rtu->w_ser.fd); + ctx_rtu->w_ser.fd = INVALID_HANDLE_VALUE; + return -1; + } + + /* Build new configuration (starting from current settings) */ + dcb = ctx_rtu->old_dcb; + + /* Speed setting */ + dcb.BaudRate = ctx_rtu->baud; + + /* Data bits */ + switch (ctx_rtu->data_bit) { + case 5: + dcb.ByteSize = 5; + break; + case 6: + dcb.ByteSize = 6; + break; + case 7: + dcb.ByteSize = 7; + break; + case 8: + default: + dcb.ByteSize = 8; + break; + } + + /* Stop bits */ + if (ctx_rtu->stop_bit == 1) + dcb.StopBits = ONESTOPBIT; + else /* 2 */ + dcb.StopBits = TWOSTOPBITS; + + /* Parity */ + if (ctx_rtu->parity == 'N') { + dcb.Parity = NOPARITY; + dcb.fParity = FALSE; + } else if (ctx_rtu->parity == 'E') { + dcb.Parity = EVENPARITY; + dcb.fParity = TRUE; + } else { + /* odd */ + dcb.Parity = ODDPARITY; + dcb.fParity = TRUE; + } + + /* Hardware handshaking left as default settings retrieved */ + + /* No software handshaking */ + dcb.fTXContinueOnXoff = TRUE; + dcb.fOutX = FALSE; + dcb.fInX = FALSE; + + /* Binary mode (it's the only supported on Windows anyway) */ + dcb.fBinary = TRUE; + + /* Don't want errors to be blocking */ + dcb.fAbortOnError = FALSE; + + /* Setup port */ + if (!SetCommState(ctx_rtu->w_ser.fd, &dcb)) { + if (ctx->debug) { + fprintf(stderr, + "ERROR Error setting new configuration (LastError %d)\n", + (int) GetLastError()); + } + CloseHandle(ctx_rtu->w_ser.fd); + ctx_rtu->w_ser.fd = INVALID_HANDLE_VALUE; + return -1; + } + + return 0; +} +#else + +static speed_t _get_termios_speed(int baud, int debug) +{ + speed_t speed; + + switch (baud) { + case 110: + speed = B110; + break; + case 300: + speed = B300; + break; + case 600: + speed = B600; + break; + case 1200: + speed = B1200; + break; + case 2400: + speed = B2400; + break; + case 4800: + speed = B4800; + break; + case 9600: + speed = B9600; + break; + case 19200: + speed = B19200; + break; + case 38400: + speed = B38400; + break; +#ifdef B57600 + case 57600: + speed = B57600; + break; +#endif +#ifdef B115200 + case 115200: + speed = B115200; + break; +#endif +#ifdef B230400 + case 230400: + speed = B230400; + break; +#endif +#ifdef B460800 + case 460800: + speed = B460800; + break; +#endif +#ifdef B500000 + case 500000: + speed = B500000; + break; +#endif +#ifdef B576000 + case 576000: + speed = B576000; + break; +#endif +#ifdef B921600 + case 921600: + speed = B921600; + break; +#endif +#ifdef B1000000 + case 1000000: + speed = B1000000; + break; +#endif +#ifdef B1152000 + case 1152000: + speed = B1152000; + break; +#endif +#ifdef B1500000 + case 1500000: + speed = B1500000; + break; +#endif +#ifdef B2500000 + case 2500000: + speed = B2500000; + break; +#endif +#ifdef B3000000 + case 3000000: + speed = B3000000; + break; +#endif +#ifdef B3500000 + case 3500000: + speed = B3500000; + break; +#endif +#ifdef B4000000 + case 4000000: + speed = B4000000; + break; +#endif + default: + speed = B9600; + if (debug) { + fprintf(stderr, "WARNING Unknown baud rate %d (B9600 used)\n", baud); + } + } + + return speed; +} + +/* POSIX */ +static int _modbus_rtu_connect(modbus_t *ctx) +{ + struct termios tios; + int flags; + speed_t speed; + modbus_rtu_t *ctx_rtu = ctx->backend_data; + + if (ctx->debug) { + printf("Opening %s at %d bauds (%c, %d, %d)\n", + ctx_rtu->device, + ctx_rtu->baud, + ctx_rtu->parity, + ctx_rtu->data_bit, + ctx_rtu->stop_bit); + } + + /* The O_NOCTTY flag tells UNIX that this program doesn't want + to be the "controlling terminal" for that port. If you + don't specify this then any input (such as keyboard abort + signals and so forth) will affect your process + + Timeouts are ignored in canonical input mode or when the + NDELAY option is set on the file via open or fcntl */ + flags = O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL; +#ifdef O_CLOEXEC + flags |= O_CLOEXEC; +#endif + + ctx->s = open(ctx_rtu->device, flags); + if (ctx->s < 0) { + if (ctx->debug) { + fprintf(stderr, + "ERROR Can't open the device %s (%s)\n", + ctx_rtu->device, + strerror(errno)); + } + return -1; + } + + /* Save */ + tcgetattr(ctx->s, &ctx_rtu->old_tios); + + memset(&tios, 0, sizeof(struct termios)); + + /* C_ISPEED Input baud (new interface) + C_OSPEED Output baud (new interface) + */ + + /* Set the baud rate */ + + /* + On MacOS, constants of baud rates are equal to the integer in argument but + that's not the case under Linux so we have to find the corresponding + constant. Until the code is upgraded to termios2, the list of possible + values is limited (no 14400 for example). + */ + if (9600 == B9600) { + speed = ctx_rtu->baud; + } else { + speed = _get_termios_speed(ctx_rtu->baud, ctx->debug); + } + + if ((cfsetispeed(&tios, speed) < 0) || (cfsetospeed(&tios, speed) < 0)) { + close(ctx->s); + ctx->s = -1; + return -1; + } + + /* C_CFLAG Control options + CLOCAL Local line - do not change "owner" of port + CREAD Enable receiver + */ + tios.c_cflag |= (CREAD | CLOCAL); + /* CSIZE, HUPCL, CRTSCTS (hardware flow control) */ + + /* Set data bits (5, 6, 7, 8 bits) + CSIZE Bit mask for data bits + */ + tios.c_cflag &= ~CSIZE; + switch (ctx_rtu->data_bit) { + case 5: + tios.c_cflag |= CS5; + break; + case 6: + tios.c_cflag |= CS6; + break; + case 7: + tios.c_cflag |= CS7; + break; + case 8: + default: + tios.c_cflag |= CS8; + break; + } + + /* Stop bit (1 or 2) */ + if (ctx_rtu->stop_bit == 1) + tios.c_cflag &= ~CSTOPB; + else /* 2 */ + tios.c_cflag |= CSTOPB; + + /* PARENB Enable parity bit + PARODD Use odd parity instead of even */ + if (ctx_rtu->parity == 'N') { + /* None */ + tios.c_cflag &= ~PARENB; + } else if (ctx_rtu->parity == 'E') { + /* Even */ + tios.c_cflag |= PARENB; + tios.c_cflag &= ~PARODD; + } else { + /* Odd */ + tios.c_cflag |= PARENB; + tios.c_cflag |= PARODD; + } + + /* Read the man page of termios if you need more information. */ + + /* This field isn't used on POSIX systems + tios.c_line = 0; + */ + + /* C_LFLAG Line options + + ISIG Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals + ICANON Enable canonical input (else raw) + XCASE Map uppercase \lowercase (obsolete) + ECHO Enable echoing of input characters + ECHOE Echo erase character as BS-SP-BS + ECHOK Echo NL after kill character + ECHONL Echo NL + NOFLSH Disable flushing of input buffers after + interrupt or quit characters + IEXTEN Enable extended functions + ECHOCTL Echo control characters as ^char and delete as ~? + ECHOPRT Echo erased character as character erased + ECHOKE BS-SP-BS entire line on line kill + FLUSHO Output being flushed + PENDIN Retype pending input at next read or input char + TOSTOP Send SIGTTOU for background output + + Canonical input is line-oriented. Input characters are put + into a buffer which can be edited interactively by the user + until a CR (carriage return) or LF (line feed) character is + received. + + Raw input is unprocessed. Input characters are passed + through exactly as they are received, when they are + received. Generally you'll deselect the ICANON, ECHO, + ECHOE, and ISIG options when using raw input + */ + + /* Raw input */ + tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + + /* C_IFLAG Input options + + Constant Description + INPCK Enable parity check + IGNPAR Ignore parity errors + PARMRK Mark parity errors + ISTRIP Strip parity bits + IXON Enable software flow control (outgoing) + IXOFF Enable software flow control (incoming) + IXANY Allow any character to start flow again + IGNBRK Ignore break condition + BRKINT Send a SIGINT when a break condition is detected + INLCR Map NL to CR + IGNCR Ignore CR + ICRNL Map CR to NL + IUCLC Map uppercase to lowercase + IMAXBEL Echo BEL on input line too long + */ + if (ctx_rtu->parity == 'N') { + /* None */ + tios.c_iflag &= ~INPCK; + } else { + tios.c_iflag |= INPCK; + } + + /* Software flow control is disabled */ + tios.c_iflag &= ~(IXON | IXOFF | IXANY); + + /* C_OFLAG Output options + OPOST Postprocess output (not set = raw output) + ONLCR Map NL to CR-NL + + ONCLR ant others needs OPOST to be enabled + */ + + /* Raw output */ + tios.c_oflag &= ~OPOST; + + /* C_CC Control characters + VMIN Minimum number of characters to read + VTIME Time to wait for data (tenths of seconds) + + UNIX serial interface drivers provide the ability to + specify character and packet timeouts. Two elements of the + c_cc array are used for timeouts: VMIN and VTIME. Timeouts + are ignored in canonical input mode or when the NDELAY + option is set on the file via open or fcntl. + + VMIN specifies the minimum number of characters to read. If + it is set to 0, then the VTIME value specifies the time to + wait for every character read. Note that this does not mean + that a read call for N bytes will wait for N characters to + come in. Rather, the timeout will apply to the first + character and the read call will return the number of + characters immediately available (up to the number you + request). + + If VMIN is non-zero, VTIME specifies the time to wait for + the first character read. If a character is read within the + time given, any read will block (wait) until all VMIN + characters are read. That is, once the first character is + read, the serial interface driver expects to receive an + entire packet of characters (VMIN bytes total). If no + character is read within the time allowed, then the call to + read returns 0. This method allows you to tell the serial + driver you need exactly N bytes and any read call will + return 0 or N bytes. However, the timeout only applies to + the first character read, so if for some reason the driver + misses one character inside the N byte packet then the read + call could block forever waiting for additional input + characters. + + VTIME specifies the amount of time to wait for incoming + characters in tenths of seconds. If VTIME is set to 0 (the + default), reads will block (wait) indefinitely unless the + NDELAY option is set on the port with open or fcntl. + */ + /* Unused because we use open with the NDELAY option */ + tios.c_cc[VMIN] = 0; + tios.c_cc[VTIME] = 0; + + if (tcsetattr(ctx->s, TCSANOW, &tios) < 0) { + close(ctx->s); + ctx->s = -1; + return -1; + } + + return 0; +} +#endif + +// FIXME Temporary solution before rewriting Windows RTU backend +static unsigned int _modbus_rtu_is_connected(modbus_t *ctx) +{ +#if defined(_WIN32) + modbus_rtu_t *ctx_rtu = ctx->backend_data; + + /* Check if file handle is valid */ + return ctx_rtu->w_ser.fd != INVALID_HANDLE_VALUE; +#else + return ctx->s >= 0; +#endif +} + +int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { +#if HAVE_DECL_TIOCSRS485 + modbus_rtu_t *ctx_rtu = ctx->backend_data; + struct serial_rs485 rs485conf; + + if (mode == MODBUS_RTU_RS485) { + // Get + if (ioctl(ctx->s, TIOCGRS485, &rs485conf) < 0) { + return -1; + } + // Set + rs485conf.flags |= SER_RS485_ENABLED; + if (ioctl(ctx->s, TIOCSRS485, &rs485conf) < 0) { + return -1; + } + + ctx_rtu->serial_mode = MODBUS_RTU_RS485; + return 0; + } else if (mode == MODBUS_RTU_RS232) { + /* Turn off RS485 mode only if required */ + if (ctx_rtu->serial_mode == MODBUS_RTU_RS485) { + /* The ioctl call is avoided because it can fail on some RS232 ports */ + if (ioctl(ctx->s, TIOCGRS485, &rs485conf) < 0) { + return -1; + } + rs485conf.flags &= ~SER_RS485_ENABLED; + if (ioctl(ctx->s, TIOCSRS485, &rs485conf) < 0) { + return -1; + } + } + ctx_rtu->serial_mode = MODBUS_RTU_RS232; + return 0; + } +#else + if (ctx->debug) { + fprintf(stderr, "This function isn't supported on your platform\n"); + } + errno = ENOTSUP; + return -1; +#endif + } + + /* Wrong backend and invalid mode specified */ + errno = EINVAL; + return -1; +} + +int modbus_rtu_get_serial_mode(modbus_t *ctx) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { +#if HAVE_DECL_TIOCSRS485 + modbus_rtu_t *ctx_rtu = ctx->backend_data; + return ctx_rtu->serial_mode; +#else + if (ctx->debug) { + fprintf(stderr, "This function isn't supported on your platform\n"); + } + errno = ENOTSUP; + return -1; +#endif + } else { + errno = EINVAL; + return -1; + } +} + +int modbus_rtu_get_rts(modbus_t *ctx) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { +#if HAVE_DECL_TIOCM_RTS + modbus_rtu_t *ctx_rtu = ctx->backend_data; + return ctx_rtu->rts; +#else + if (ctx->debug) { + fprintf(stderr, "This function isn't supported on your platform\n"); + } + errno = ENOTSUP; + return -1; +#endif + } else { + errno = EINVAL; + return -1; + } +} + +int modbus_rtu_set_rts(modbus_t *ctx, int mode) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { +#if HAVE_DECL_TIOCM_RTS + modbus_rtu_t *ctx_rtu = ctx->backend_data; + + if (mode == MODBUS_RTU_RTS_NONE || mode == MODBUS_RTU_RTS_UP || + mode == MODBUS_RTU_RTS_DOWN) { + ctx_rtu->rts = mode; + + /* Set the RTS bit in order to not reserve the RS485 bus */ + ctx_rtu->set_rts(ctx, ctx_rtu->rts != MODBUS_RTU_RTS_UP); + + return 0; + } else { + errno = EINVAL; + return -1; + } +#else + if (ctx->debug) { + fprintf(stderr, "This function isn't supported on your platform\n"); + } + errno = ENOTSUP; + return -1; +#endif + } + /* Wrong backend or invalid mode specified */ + errno = EINVAL; + return -1; +} + +int modbus_rtu_set_custom_rts(modbus_t *ctx, void (*set_rts)(modbus_t *ctx, int on)) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { +#if HAVE_DECL_TIOCM_RTS + modbus_rtu_t *ctx_rtu = ctx->backend_data; + ctx_rtu->set_rts = set_rts; + return 0; +#else + if (ctx->debug) { + fprintf(stderr, "This function isn't supported on your platform\n"); + } + errno = ENOTSUP; + return -1; +#endif + } else { + errno = EINVAL; + return -1; + } +} + +int modbus_rtu_get_rts_delay(modbus_t *ctx) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { +#if HAVE_DECL_TIOCM_RTS + modbus_rtu_t *ctx_rtu; + ctx_rtu = (modbus_rtu_t *) ctx->backend_data; + return ctx_rtu->rts_delay; +#else + if (ctx->debug) { + fprintf(stderr, "This function isn't supported on your platform\n"); + } + errno = ENOTSUP; + return -1; +#endif + } else { + errno = EINVAL; + return -1; + } +} + +int modbus_rtu_set_rts_delay(modbus_t *ctx, int us) +{ + if (ctx == NULL || us < 0) { + errno = EINVAL; + return -1; + } + + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { +#if HAVE_DECL_TIOCM_RTS + modbus_rtu_t *ctx_rtu; + ctx_rtu = (modbus_rtu_t *) ctx->backend_data; + ctx_rtu->rts_delay = us; + return 0; +#else + if (ctx->debug) { + fprintf(stderr, "This function isn't supported on your platform\n"); + } + errno = ENOTSUP; + return -1; +#endif + } else { + errno = EINVAL; + return -1; + } +} + +static void _modbus_rtu_close(modbus_t *ctx) +{ + /* Restore line settings and close file descriptor in RTU mode */ + modbus_rtu_t *ctx_rtu = ctx->backend_data; + +#if defined(_WIN32) + /* Revert settings */ + if (!SetCommState(ctx_rtu->w_ser.fd, &ctx_rtu->old_dcb) && ctx->debug) { + fprintf(stderr, + "ERROR Couldn't revert to configuration (LastError %d)\n", + (int) GetLastError()); + } + + if (!CloseHandle(ctx_rtu->w_ser.fd) && ctx->debug) { + fprintf(stderr, + "ERROR Error while closing handle (LastError %d)\n", + (int) GetLastError()); + } +#else + if (ctx->s >= 0) { + tcsetattr(ctx->s, TCSANOW, &ctx_rtu->old_tios); + close(ctx->s); + ctx->s = -1; + } +#endif +} + +static int _modbus_rtu_flush(modbus_t *ctx) +{ +#if defined(_WIN32) + modbus_rtu_t *ctx_rtu = ctx->backend_data; + ctx_rtu->w_ser.n_bytes = 0; + return (PurgeComm(ctx_rtu->w_ser.fd, PURGE_RXCLEAR) == FALSE); +#else + return tcflush(ctx->s, TCIOFLUSH); +#endif +} + +static int +_modbus_rtu_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_to_read) +{ + int s_rc; +#if defined(_WIN32) + s_rc = win32_ser_select( + &((modbus_rtu_t *) ctx->backend_data)->w_ser, length_to_read, tv); + if (s_rc == 0) { + errno = ETIMEDOUT; + return -1; + } + + if (s_rc < 0) { + return -1; + } +#else + while ((s_rc = select(ctx->s + 1, rset, NULL, NULL, tv)) == -1) { + if (errno == EINTR) { + if (ctx->debug) { + fprintf(stderr, "A non blocked signal was caught\n"); + } + /* Necessary after an error */ + FD_ZERO(rset); + FD_SET(ctx->s, rset); + } else { + return -1; + } + } + + if (s_rc == 0) { + /* Timeout */ + errno = ETIMEDOUT; + return -1; + } +#endif + + return s_rc; +} + +static void _modbus_rtu_free(modbus_t *ctx) +{ + if (ctx->backend_data) { + free(((modbus_rtu_t *) ctx->backend_data)->device); + free(ctx->backend_data); + } + + free(ctx); +} + +// clang-format off +const modbus_backend_t _modbus_rtu_backend = { + _MODBUS_BACKEND_TYPE_RTU, + _MODBUS_RTU_HEADER_LENGTH, + _MODBUS_RTU_CHECKSUM_LENGTH, + MODBUS_RTU_MAX_ADU_LENGTH, + _modbus_set_slave, + _modbus_rtu_build_request_basis, + _modbus_rtu_build_response_basis, + _modbus_rtu_prepare_response_tid, + _modbus_rtu_send_msg_pre, + _modbus_rtu_send, + _modbus_rtu_receive, + _modbus_rtu_recv, + _modbus_rtu_check_integrity, + _modbus_rtu_pre_check_confirmation, + _modbus_rtu_connect, + _modbus_rtu_is_connected, + _modbus_rtu_close, + _modbus_rtu_flush, + _modbus_rtu_select, + _modbus_rtu_free +}; + +// clang-format on + +modbus_t * +modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit) +{ + modbus_t *ctx; + modbus_rtu_t *ctx_rtu; + + /* Check device argument */ + if (device == NULL || *device == 0) { + fprintf(stderr, "The device string is empty\n"); + errno = EINVAL; + return NULL; + } + + /* Check baud argument */ + if (baud == 0) { + fprintf(stderr, "The baud rate value must not be zero\n"); + errno = EINVAL; + return NULL; + } + + ctx = (modbus_t *) malloc(sizeof(modbus_t)); + if (ctx == NULL) { + return NULL; + } + + _modbus_init_common(ctx); + ctx->backend = &_modbus_rtu_backend; + ctx->backend_data = (modbus_rtu_t *) malloc(sizeof(modbus_rtu_t)); + if (ctx->backend_data == NULL) { + modbus_free(ctx); + errno = ENOMEM; + return NULL; + } + ctx_rtu = (modbus_rtu_t *) ctx->backend_data; + + /* Device name and \0 */ + ctx_rtu->device = (char *) malloc((strlen(device) + 1) * sizeof(char)); + if (ctx_rtu->device == NULL) { + modbus_free(ctx); + errno = ENOMEM; + return NULL; + } + +#if defined(_WIN32) + strcpy_s(ctx_rtu->device, strlen(device) + 1, device); +#else + strcpy(ctx_rtu->device, device); +#endif + + ctx_rtu->baud = baud; + if (parity == 'N' || parity == 'E' || parity == 'O') { + ctx_rtu->parity = parity; + } else { + modbus_free(ctx); + errno = EINVAL; + return NULL; + } + ctx_rtu->data_bit = data_bit; + ctx_rtu->stop_bit = stop_bit; + +#if HAVE_DECL_TIOCSRS485 + /* The RS232 mode has been set by default */ + ctx_rtu->serial_mode = MODBUS_RTU_RS232; +#endif + +#if HAVE_DECL_TIOCM_RTS + /* The RTS use has been set by default */ + ctx_rtu->rts = MODBUS_RTU_RTS_NONE; + + /* Calculate estimated time in micro second to send one byte */ + ctx_rtu->onebyte_time = + 1000000 * (1 + data_bit + (parity == 'N' ? 0 : 1) + stop_bit) / baud; + + /* The internal function is used by default to set RTS */ + ctx_rtu->set_rts = _modbus_rtu_ioctl_rts; + + /* The delay before and after transmission when toggling the RTS pin */ + ctx_rtu->rts_delay = ctx_rtu->onebyte_time; +#endif + + ctx_rtu->confirmation_to_ignore = FALSE; + + return ctx; +} diff --git a/src/libmodbus/src/modbus-tcp.c b/src/libmodbus/src/modbus-tcp.c new file mode 100644 index 0000000..8389eae --- /dev/null +++ b/src/libmodbus/src/modbus-tcp.c @@ -0,0 +1,974 @@ +/* + * Copyright © Stéphane Raimbault + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +// clang-format off +#if defined(_WIN32) +# define OS_WIN32 +/* ws2_32.dll has getaddrinfo and freeaddrinfo on Windows XP and later. + * minwg32 headers check WINVER before allowing the use of these */ +# ifndef WINVER +# define WINVER 0x0501 +# endif +#endif + +#include +#include +#include +#include +#ifndef _MSC_VER +#include +#endif +#include +#include + +#if defined(_WIN32) +/* Already set in modbus-tcp.h but it seems order matters in VS2005 */ +# include +# include +# define SHUT_RDWR 2 +# define close closesocket +# define strdup _strdup +#else +# include +# include + +#if defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD__ < 5) +# define OS_BSD +# include +#endif + +# include +# include +# include +# include +# include +#endif + +#if !defined(MSG_NOSIGNAL) +#define MSG_NOSIGNAL 0 +#endif + +#if defined(_AIX) && !defined(MSG_DONTWAIT) +#define MSG_DONTWAIT MSG_NONBLOCK +#endif +// clang-format on + +#include "modbus-private.h" + +#include "modbus-tcp-private.h" +#include "modbus-tcp.h" + +#ifdef OS_WIN32 +static int _modbus_tcp_init_win32(void) +{ + /* Initialise Windows Socket API */ + WSADATA wsaData; + + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + fprintf(stderr, + "WSAStartup() returned error code %d\n", + (unsigned int) GetLastError()); + errno = EIO; + return -1; + } + return 0; +} +#endif + +static int _modbus_set_slave(modbus_t *ctx, int slave) +{ + int max_slave = (ctx->quirks & MODBUS_QUIRK_MAX_SLAVE) ? 255 : 247; + + /* Broadcast address is 0 (MODBUS_BROADCAST_ADDRESS) */ + if (slave >= 0 && slave <= max_slave) { + ctx->slave = slave; + } else if (slave == MODBUS_TCP_SLAVE) { + /* The special value MODBUS_TCP_SLAVE (0xFF) can be used in TCP mode to + * restore the default value. */ + ctx->slave = slave; + } else { + errno = EINVAL; + return -1; + } + + return 0; +} + +/* Builds a TCP request header */ +static int _modbus_tcp_build_request_basis( + modbus_t *ctx, int function, int addr, int nb, uint8_t *req) +{ + modbus_tcp_t *ctx_tcp = ctx->backend_data; + + /* Increase transaction ID */ + if (ctx_tcp->t_id < UINT16_MAX) + ctx_tcp->t_id++; + else + ctx_tcp->t_id = 0; + req[0] = ctx_tcp->t_id >> 8; + req[1] = ctx_tcp->t_id & 0x00ff; + + /* Protocol Modbus */ + req[2] = 0; + req[3] = 0; + + /* Length will be defined later by set_req_length_tcp at offsets 4 + and 5 */ + + req[6] = ctx->slave; + req[7] = function; + req[8] = addr >> 8; + req[9] = addr & 0x00ff; + req[10] = nb >> 8; + req[11] = nb & 0x00ff; + + return _MODBUS_TCP_PRESET_REQ_LENGTH; +} + +/* Builds a TCP response header */ +static int _modbus_tcp_build_response_basis(sft_t *sft, uint8_t *rsp) +{ + /* Extract from MODBUS Messaging on TCP/IP Implementation + Guide V1.0b (page 23/46): + The transaction identifier is used to associate the future + response with the request. */ + rsp[0] = sft->t_id >> 8; + rsp[1] = sft->t_id & 0x00ff; + + /* Protocol Modbus */ + rsp[2] = 0; + rsp[3] = 0; + + /* Length will be set later by send_msg (4 and 5) */ + + /* The slave ID is copied from the indication */ + rsp[6] = sft->slave; + rsp[7] = sft->function; + + return _MODBUS_TCP_PRESET_RSP_LENGTH; +} + +static int _modbus_tcp_prepare_response_tid(const uint8_t *req, int *req_length) +{ + return (req[0] << 8) + req[1]; +} + +static int _modbus_tcp_send_msg_pre(uint8_t *req, int req_length) +{ + /* Subtract the header length to the message length */ + int mbap_length = req_length - 6; + + req[4] = mbap_length >> 8; + req[5] = mbap_length & 0x00FF; + + return req_length; +} + +static ssize_t _modbus_tcp_send(modbus_t *ctx, const uint8_t *req, int req_length) +{ + /* MSG_NOSIGNAL + Requests not to send SIGPIPE on errors on stream oriented + sockets when the other end breaks the connection. The EPIPE + error is still returned. */ + return send(ctx->s, (const char *) req, req_length, MSG_NOSIGNAL); +} + +static int _modbus_tcp_receive(modbus_t *ctx, uint8_t *req) +{ + return _modbus_receive_msg(ctx, req, MSG_INDICATION); +} + +static ssize_t _modbus_tcp_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length) +{ + return recv(ctx->s, (char *) rsp, rsp_length, 0); +} + +static int _modbus_tcp_check_integrity(modbus_t *ctx, uint8_t *msg, const int msg_length) +{ + return msg_length; +} + +static int _modbus_tcp_pre_check_confirmation(modbus_t *ctx, + const uint8_t *req, + const uint8_t *rsp, + int rsp_length) +{ + unsigned int protocol_id; + /* Check transaction ID */ + if (req[0] != rsp[0] || req[1] != rsp[1]) { + if (ctx->debug) { + fprintf(stderr, + "Invalid transaction ID received 0x%X (not 0x%X)\n", + (rsp[0] << 8) + rsp[1], + (req[0] << 8) + req[1]); + } + errno = EMBBADDATA; + return -1; + } + + /* Check protocol ID */ + protocol_id = (rsp[2] << 8) + rsp[3]; + if (protocol_id != 0x0) { + if (ctx->debug) { + fprintf(stderr, "Invalid protocol ID received 0x%X (not 0x0)\n", protocol_id); + } + errno = EMBBADDATA; + return -1; + } + + return 0; +} + +static int _modbus_tcp_set_ipv4_options(int s) +{ + int rc; + int option; + + /* Set the TCP no delay flag */ + /* SOL_TCP = IPPROTO_TCP */ + option = 1; + rc = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (const void *) &option, sizeof(int)); + if (rc == -1) { + return -1; + } + + /* If the OS does not offer SOCK_NONBLOCK, fall back to setting FIONBIO to + * make sockets non-blocking */ + /* Do not care about the return value, this is optional */ +#if !defined(SOCK_NONBLOCK) && defined(FIONBIO) +#ifdef OS_WIN32 + { + /* Setting FIONBIO expects an unsigned long according to MSDN */ + u_long loption = 1; + ioctlsocket(s, FIONBIO, &loption); + } +#else + option = 1; + ioctl(s, FIONBIO, &option); +#endif +#endif + +#ifndef OS_WIN32 + /** + * Cygwin defines IPTOS_LOWDELAY but can't handle that flag so it's + * necessary to workaround that problem. + **/ + /* Set the IP low delay option */ + option = IPTOS_LOWDELAY; + rc = setsockopt(s, IPPROTO_IP, IP_TOS, (const void *) &option, sizeof(int)); + if (rc == -1) { + return -1; + } +#endif + + return 0; +} + +static int _connect(int sockfd, + const struct sockaddr *addr, + socklen_t addrlen, + const struct timeval *ro_tv) +{ + int rc = connect(sockfd, addr, addrlen); + +#ifdef OS_WIN32 + int wsaError = 0; + if (rc == -1) { + wsaError = WSAGetLastError(); + } + + if (wsaError == WSAEWOULDBLOCK || wsaError == WSAEINPROGRESS) { +#else + if (rc == -1 && errno == EINPROGRESS) { +#endif + fd_set wset; + int optval; + socklen_t optlen = sizeof(optval); + struct timeval tv = *ro_tv; + + /* Wait to be available in writing */ + FD_ZERO(&wset); + FD_SET(sockfd, &wset); + rc = select(sockfd + 1, NULL, &wset, NULL, &tv); + if (rc <= 0) { + /* Timeout or fail */ + return -1; + } + + /* The connection is established if SO_ERROR and optval are set to 0 */ + rc = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen); + if (rc == 0 && optval == 0) { + return 0; + } else { + errno = ECONNREFUSED; + return -1; + } + } + return rc; +} + +/* Establishes a modbus TCP connection with a Modbus server. */ +static int _modbus_tcp_connect(modbus_t *ctx) +{ + int rc; + /* Specialized version of sockaddr for Internet socket address (same size) */ + struct sockaddr_in addr; + modbus_tcp_t *ctx_tcp = ctx->backend_data; + int flags = SOCK_STREAM; + +#ifdef OS_WIN32 + if (_modbus_tcp_init_win32() == -1) { + return -1; + } +#endif + +#ifdef SOCK_CLOEXEC + flags |= SOCK_CLOEXEC; +#endif + +#ifdef SOCK_NONBLOCK + flags |= SOCK_NONBLOCK; +#endif + + ctx->s = socket(PF_INET, flags, 0); + if (ctx->s < 0) { + return -1; + } + + rc = _modbus_tcp_set_ipv4_options(ctx->s); + if (rc == -1) { + close(ctx->s); + ctx->s = -1; + return -1; + } + + if (ctx->debug) { + printf("Connecting to %s:%d\n", ctx_tcp->ip, ctx_tcp->port); + } + + addr.sin_family = AF_INET; + addr.sin_port = htons(ctx_tcp->port); + rc = inet_pton(addr.sin_family, ctx_tcp->ip, &(addr.sin_addr)); + if (rc <= 0) { + if (ctx->debug) { + fprintf(stderr, "Invalid IP address: %s\n", ctx_tcp->ip); + } + close(ctx->s); + ctx->s = -1; + return -1; + } + + rc = + _connect(ctx->s, (struct sockaddr *) &addr, sizeof(addr), &ctx->response_timeout); + if (rc == -1) { + close(ctx->s); + ctx->s = -1; + return -1; + } + + return 0; +} + +/* Establishes a modbus TCP PI connection with a Modbus server. */ +static int _modbus_tcp_pi_connect(modbus_t *ctx) +{ + int rc; + struct addrinfo *ai_list; + struct addrinfo *ai_ptr; + struct addrinfo ai_hints; + modbus_tcp_pi_t *ctx_tcp_pi = ctx->backend_data; + +#ifdef OS_WIN32 + if (_modbus_tcp_init_win32() == -1) { + return -1; + } +#endif + + memset(&ai_hints, 0, sizeof(ai_hints)); +#ifdef AI_ADDRCONFIG + ai_hints.ai_flags |= AI_ADDRCONFIG; +#endif + ai_hints.ai_family = AF_UNSPEC; + ai_hints.ai_socktype = SOCK_STREAM; + ai_hints.ai_addr = NULL; + ai_hints.ai_canonname = NULL; + ai_hints.ai_next = NULL; + + ai_list = NULL; + rc = getaddrinfo(ctx_tcp_pi->node, ctx_tcp_pi->service, &ai_hints, &ai_list); + if (rc != 0) { + if (ctx->debug) { + fprintf(stderr, "Error returned by getaddrinfo: %s\n", gai_strerror(rc)); + } + errno = ECONNREFUSED; + return -1; + } + + for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) { + int flags = ai_ptr->ai_socktype; + int s; + +#ifdef SOCK_CLOEXEC + flags |= SOCK_CLOEXEC; +#endif + +#ifdef SOCK_NONBLOCK + flags |= SOCK_NONBLOCK; +#endif + + s = socket(ai_ptr->ai_family, flags, ai_ptr->ai_protocol); + if (s < 0) + continue; + + if (ai_ptr->ai_family == AF_INET) + _modbus_tcp_set_ipv4_options(s); + + if (ctx->debug) { + printf("Connecting to [%s]:%s\n", ctx_tcp_pi->node, ctx_tcp_pi->service); + } + + rc = _connect(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen, &ctx->response_timeout); + if (rc == -1) { + close(s); + continue; + } + + ctx->s = s; + break; + } + + freeaddrinfo(ai_list); + + if (ctx->s < 0) { + return -1; + } + + return 0; +} + +static unsigned int _modbus_tcp_is_connected(modbus_t *ctx) +{ + return ctx->s >= 0; +} + +/* Closes the network connection and socket in TCP mode */ +static void _modbus_tcp_close(modbus_t *ctx) +{ + if (ctx->s >= 0) { + shutdown(ctx->s, SHUT_RDWR); + close(ctx->s); + ctx->s = -1; + } +} + +static int _modbus_tcp_flush(modbus_t *ctx) +{ + int rc; + int rc_sum = 0; + + do { + /* Extract the garbage from the socket */ + char devnull[MODBUS_TCP_MAX_ADU_LENGTH]; +#ifndef OS_WIN32 + rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, MSG_DONTWAIT); +#else + /* On Win32, it's a bit more complicated to not wait */ + fd_set rset; + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = 0; + FD_ZERO(&rset); + FD_SET(ctx->s, &rset); + rc = select(ctx->s + 1, &rset, NULL, NULL, &tv); + if (rc == -1) { + return -1; + } + + if (rc == 1) { + /* There is data to flush */ + rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, 0); + } +#endif + if (rc > 0) { + rc_sum += rc; + } + } while (rc == MODBUS_TCP_MAX_ADU_LENGTH); + + return rc_sum; +} + +/* Listens for any request from one or many modbus masters in TCP */ +int modbus_tcp_listen(modbus_t *ctx, int nb_connection) +{ + int new_s; + int enable; + int flags; + struct sockaddr_in addr; + modbus_tcp_t *ctx_tcp; + int rc; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + ctx_tcp = ctx->backend_data; + +#ifdef OS_WIN32 + if (_modbus_tcp_init_win32() == -1) { + return -1; + } +#endif + + flags = SOCK_STREAM; + +#ifdef SOCK_CLOEXEC + flags |= SOCK_CLOEXEC; +#endif + + new_s = socket(PF_INET, flags, IPPROTO_TCP); + if (new_s == -1) { + return -1; + } + + enable = 1; + if (setsockopt(new_s, SOL_SOCKET, SO_REUSEADDR, (char *) &enable, sizeof(enable)) == + -1) { + close(new_s); + return -1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + /* If the modbus port is < to 1024, we need the setuid root. */ + addr.sin_port = htons(ctx_tcp->port); + if (ctx_tcp->ip[0] == '0') { + /* Listen any addresses */ + addr.sin_addr.s_addr = htonl(INADDR_ANY); + } else { + /* Listen only specified IP address */ + rc = inet_pton(addr.sin_family, ctx_tcp->ip, &(addr.sin_addr)); + if (rc <= 0) { + if (ctx->debug) { + fprintf(stderr, "Invalid IP address: %s\n", ctx_tcp->ip); + } + close(new_s); + return -1; + } + } + + if (bind(new_s, (struct sockaddr *) &addr, sizeof(addr)) == -1) { + close(new_s); + return -1; + } + + if (listen(new_s, nb_connection) == -1) { + close(new_s); + return -1; + } + + return new_s; +} + +int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection) +{ + int rc; + struct addrinfo *ai_list; + struct addrinfo *ai_ptr; + struct addrinfo ai_hints; + const char *node; + const char *service; + int new_s; + modbus_tcp_pi_t *ctx_tcp_pi; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + ctx_tcp_pi = ctx->backend_data; + +#ifdef OS_WIN32 + if (_modbus_tcp_init_win32() == -1) { + return -1; + } +#endif + + if (ctx_tcp_pi->node[0] == 0) { + node = NULL; /* == any */ + } else { + node = ctx_tcp_pi->node; + } + + if (ctx_tcp_pi->service[0] == 0) { + service = "502"; + } else { + service = ctx_tcp_pi->service; + } + + memset(&ai_hints, 0, sizeof(ai_hints)); + /* If node is not NULL, than the AI_PASSIVE flag is ignored. */ + ai_hints.ai_flags |= AI_PASSIVE; +#ifdef AI_ADDRCONFIG + ai_hints.ai_flags |= AI_ADDRCONFIG; +#endif + ai_hints.ai_family = AF_UNSPEC; + ai_hints.ai_socktype = SOCK_STREAM; + ai_hints.ai_addr = NULL; + ai_hints.ai_canonname = NULL; + ai_hints.ai_next = NULL; + + ai_list = NULL; + rc = getaddrinfo(node, service, &ai_hints, &ai_list); + if (rc != 0) { + if (ctx->debug) { + fprintf(stderr, "Error returned by getaddrinfo: %s\n", gai_strerror(rc)); + } + errno = ECONNREFUSED; + return -1; + } + + new_s = -1; + for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) { + int flags = ai_ptr->ai_socktype; + int s; + +#ifdef SOCK_CLOEXEC + flags |= SOCK_CLOEXEC; +#endif + + s = socket(ai_ptr->ai_family, flags, ai_ptr->ai_protocol); + if (s < 0) { + if (ctx->debug) { + perror("socket"); + } + continue; + } else { + int enable = 1; + rc = + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *) &enable, sizeof(enable)); + if (rc != 0) { + close(s); + if (ctx->debug) { + perror("setsockopt"); + } + continue; + } + } + + rc = bind(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen); + if (rc != 0) { + close(s); + if (ctx->debug) { + perror("bind"); + } + continue; + } + + rc = listen(s, nb_connection); + if (rc != 0) { + close(s); + if (ctx->debug) { + perror("listen"); + } + continue; + } + + new_s = s; + break; + } + freeaddrinfo(ai_list); + + if (new_s < 0) { + return -1; + } + + return new_s; +} + +int modbus_tcp_accept(modbus_t *ctx, int *s) +{ + struct sockaddr_in addr; + socklen_t addrlen; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + addrlen = sizeof(addr); +#ifdef HAVE_ACCEPT4 + /* Inherit socket flags and use accept4 call */ + ctx->s = accept4(*s, (struct sockaddr *) &addr, &addrlen, SOCK_CLOEXEC); +#else + ctx->s = accept(*s, (struct sockaddr *) &addr, &addrlen); +#endif + + if (ctx->s < 0) { + return -1; + } + + if (ctx->debug) { + char buf[INET_ADDRSTRLEN]; + if (inet_ntop(AF_INET, &(addr.sin_addr), buf, INET_ADDRSTRLEN) == NULL) { + fprintf(stderr, "Client connection accepted from unparsable IP.\n"); + } else { + printf("Client connection accepted from %s.\n", buf); + } + } + + return ctx->s; +} + +int modbus_tcp_pi_accept(modbus_t *ctx, int *s) +{ + struct sockaddr_in6 addr; + socklen_t addrlen; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + addrlen = sizeof(addr); +#ifdef HAVE_ACCEPT4 + /* Inherit socket flags and use accept4 call */ + ctx->s = accept4(*s, (struct sockaddr *) &addr, &addrlen, SOCK_CLOEXEC); +#else + ctx->s = accept(*s, (struct sockaddr *) &addr, &addrlen); +#endif + + if (ctx->s < 0) { + return -1; + } + + if (ctx->debug) { + char buf[INET6_ADDRSTRLEN]; + if (inet_ntop(AF_INET6, &(addr.sin6_addr), buf, INET6_ADDRSTRLEN) == NULL) { + fprintf(stderr, "Client connection accepted from unparsable IP.\n"); + } else { + printf("Client connection accepted from %s.\n", buf); + } + } + + return ctx->s; +} + +static int +_modbus_tcp_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_to_read) +{ + int s_rc; + while ((s_rc = select(ctx->s + 1, rset, NULL, NULL, tv)) == -1) { + if (errno == EINTR) { + if (ctx->debug) { + fprintf(stderr, "A non blocked signal was caught\n"); + } + /* Necessary after an error */ + FD_ZERO(rset); + FD_SET(ctx->s, rset); + } else { + return -1; + } + } + + if (s_rc == 0) { + errno = ETIMEDOUT; + return -1; + } + + return s_rc; +} + +static void _modbus_tcp_free(modbus_t *ctx) +{ + if (ctx->backend_data) { + free(ctx->backend_data); + } + free(ctx); +} + +static void _modbus_tcp_pi_free(modbus_t *ctx) +{ + if (ctx->backend_data) { + modbus_tcp_pi_t *ctx_tcp_pi = ctx->backend_data; + free(ctx_tcp_pi->node); + free(ctx_tcp_pi->service); + free(ctx->backend_data); + } + + free(ctx); +} + +// clang-format off +const modbus_backend_t _modbus_tcp_backend = { + _MODBUS_BACKEND_TYPE_TCP, + _MODBUS_TCP_HEADER_LENGTH, + _MODBUS_TCP_CHECKSUM_LENGTH, + MODBUS_TCP_MAX_ADU_LENGTH, + _modbus_set_slave, + _modbus_tcp_build_request_basis, + _modbus_tcp_build_response_basis, + _modbus_tcp_prepare_response_tid, + _modbus_tcp_send_msg_pre, + _modbus_tcp_send, + _modbus_tcp_receive, + _modbus_tcp_recv, + _modbus_tcp_check_integrity, + _modbus_tcp_pre_check_confirmation, + _modbus_tcp_connect, + _modbus_tcp_is_connected, + _modbus_tcp_close, + _modbus_tcp_flush, + _modbus_tcp_select, + _modbus_tcp_free +}; + +const modbus_backend_t _modbus_tcp_pi_backend = { + _MODBUS_BACKEND_TYPE_TCP, + _MODBUS_TCP_HEADER_LENGTH, + _MODBUS_TCP_CHECKSUM_LENGTH, + MODBUS_TCP_MAX_ADU_LENGTH, + _modbus_set_slave, + _modbus_tcp_build_request_basis, + _modbus_tcp_build_response_basis, + _modbus_tcp_prepare_response_tid, + _modbus_tcp_send_msg_pre, + _modbus_tcp_send, + _modbus_tcp_receive, + _modbus_tcp_recv, + _modbus_tcp_check_integrity, + _modbus_tcp_pre_check_confirmation, + _modbus_tcp_pi_connect, + _modbus_tcp_is_connected, + _modbus_tcp_close, + _modbus_tcp_flush, + _modbus_tcp_select, + _modbus_tcp_pi_free +}; + +// clang-format on + +modbus_t *modbus_new_tcp(const char *ip, int port) +{ + modbus_t *ctx; + modbus_tcp_t *ctx_tcp; + size_t dest_size; + size_t ret_size; + +#if defined(OS_BSD) + /* MSG_NOSIGNAL is unsupported on *BSD so we install an ignore + handler for SIGPIPE. */ + struct sigaction sa; + + sa.sa_handler = SIG_IGN; + if (sigaction(SIGPIPE, &sa, NULL) < 0) { + /* The debug flag can't be set here... */ + fprintf(stderr, "Could not install SIGPIPE handler.\n"); + return NULL; + } +#endif + + ctx = (modbus_t *) malloc(sizeof(modbus_t)); + if (ctx == NULL) { + return NULL; + } + _modbus_init_common(ctx); + + /* Could be changed after to reach a remote serial Modbus device */ + ctx->slave = MODBUS_TCP_SLAVE; + + ctx->backend = &_modbus_tcp_backend; + + ctx->backend_data = (modbus_tcp_t *) malloc(sizeof(modbus_tcp_t)); + if (ctx->backend_data == NULL) { + modbus_free(ctx); + errno = ENOMEM; + return NULL; + } + ctx_tcp = (modbus_tcp_t *) ctx->backend_data; + + if (ip != NULL) { + dest_size = sizeof(char) * 16; + ret_size = strlcpy(ctx_tcp->ip, ip, dest_size); + if (ret_size == 0) { + fprintf(stderr, "The IP string is empty\n"); + modbus_free(ctx); + errno = EINVAL; + return NULL; + } + + if (ret_size >= dest_size) { + fprintf(stderr, "The IP string has been truncated\n"); + modbus_free(ctx); + errno = EINVAL; + return NULL; + } + } else { + ctx_tcp->ip[0] = '0'; + } + ctx_tcp->port = port; + ctx_tcp->t_id = 0; + + return ctx; +} + +modbus_t *modbus_new_tcp_pi(const char *node, const char *service) +{ + modbus_t *ctx; + modbus_tcp_pi_t *ctx_tcp_pi; + + ctx = (modbus_t *) malloc(sizeof(modbus_t)); + if (ctx == NULL) { + return NULL; + } + _modbus_init_common(ctx); + + /* Could be changed after to reach a remote serial Modbus device */ + ctx->slave = MODBUS_TCP_SLAVE; + + ctx->backend = &_modbus_tcp_pi_backend; + + ctx->backend_data = (modbus_tcp_pi_t *) malloc(sizeof(modbus_tcp_pi_t)); + if (ctx->backend_data == NULL) { + modbus_free(ctx); + errno = ENOMEM; + return NULL; + } + ctx_tcp_pi = (modbus_tcp_pi_t *) ctx->backend_data; + ctx_tcp_pi->node = NULL; + ctx_tcp_pi->service = NULL; + + if (node != NULL) { + ctx_tcp_pi->node = strdup(node); + } else { + /* The node argument can be empty to indicate any hosts */ + ctx_tcp_pi->node = strdup(""); + } + + if (ctx_tcp_pi->node == NULL) { + modbus_free(ctx); + errno = ENOMEM; + return NULL; + } + + if (service != NULL && service[0] != '\0') { + ctx_tcp_pi->service = strdup(service); + } else { + /* Default Modbus port number */ + ctx_tcp_pi->service = strdup("502"); + } + + if (ctx_tcp_pi->service == NULL) { + modbus_free(ctx); + errno = ENOMEM; + return NULL; + } + + ctx_tcp_pi->t_id = 0; + + return ctx; +} diff --git a/src/libmodbus/src/modbus.c b/src/libmodbus/src/modbus.c new file mode 100644 index 0000000..7494a48 --- /dev/null +++ b/src/libmodbus/src/modbus.c @@ -0,0 +1,2071 @@ +/* + * Copyright © Stéphane Raimbault + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This library implements the Modbus protocol. + * http://libmodbus.org/ + */ + +#include +#include +#include +#include +#include +#include +#include +#ifndef _MSC_VER +#include +#endif + +#include + +#include "modbus-private.h" +#include "modbus.h" + +/* Internal use */ +#define MSG_LENGTH_UNDEFINED -1 + +/* Exported version */ +const unsigned int libmodbus_version_major = LIBMODBUS_VERSION_MAJOR; +const unsigned int libmodbus_version_minor = LIBMODBUS_VERSION_MINOR; +const unsigned int libmodbus_version_micro = LIBMODBUS_VERSION_MICRO; + +/* Max between RTU and TCP max adu length (so TCP) */ +#define MAX_MESSAGE_LENGTH 260 + +/* 3 steps are used to parse the query */ +typedef enum { + _STEP_FUNCTION, + _STEP_META, + _STEP_DATA +} _step_t; + +const char *modbus_strerror(int errnum) +{ + switch (errnum) { + case EMBXILFUN: + return "Illegal function"; + case EMBXILADD: + return "Illegal data address"; + case EMBXILVAL: + return "Illegal data value"; + case EMBXSFAIL: + return "Slave device or server failure"; + case EMBXACK: + return "Acknowledge"; + case EMBXSBUSY: + return "Slave device or server is busy"; + case EMBXNACK: + return "Negative acknowledge"; + case EMBXMEMPAR: + return "Memory parity error"; + case EMBXGPATH: + return "Gateway path unavailable"; + case EMBXGTAR: + return "Target device failed to respond"; + case EMBBADCRC: + return "Invalid CRC"; + case EMBBADDATA: + return "Invalid data"; + case EMBBADEXC: + return "Invalid exception code"; + case EMBMDATA: + return "Too many data"; + case EMBBADSLAVE: + return "Response not from requested slave"; + default: + return strerror(errnum); + } +} + +void _error_print(modbus_t *ctx, const char *context) +{ + if (ctx->debug) { + fprintf(stderr, "ERROR %s", modbus_strerror(errno)); + if (context != NULL) { + fprintf(stderr, ": %s\n", context); + } else { + fprintf(stderr, "\n"); + } + } +} + +static void _sleep_response_timeout(modbus_t *ctx) +{ + /* Response timeout is always positive */ +#ifdef _WIN32 + /* usleep doesn't exist on Windows */ + Sleep((ctx->response_timeout.tv_sec * 1000) + (ctx->response_timeout.tv_usec / 1000)); +#else + /* usleep source code */ + struct timespec request, remaining; + request.tv_sec = ctx->response_timeout.tv_sec; + request.tv_nsec = ((long int) ctx->response_timeout.tv_usec) * 1000; + while (nanosleep(&request, &remaining) == -1 && errno == EINTR) { + request = remaining; + } +#endif +} + +int modbus_flush(modbus_t *ctx) +{ + int rc; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + rc = ctx->backend->flush(ctx); + if (rc != -1 && ctx->debug) { + /* Not all backends are able to return the number of bytes flushed */ + printf("Bytes flushed (%d)\n", rc); + } + return rc; +} + +/* Computes the length of the expected response */ +static unsigned int compute_response_length_from_request(modbus_t *ctx, uint8_t *req) +{ + int length; + const int offset = ctx->backend->header_length; + + switch (req[offset]) { + case MODBUS_FC_READ_COILS: + case MODBUS_FC_READ_DISCRETE_INPUTS: { + /* Header + nb values (code from write_bits) */ + int nb = (req[offset + 3] << 8) | req[offset + 4]; + length = 2 + (nb / 8) + ((nb % 8) ? 1 : 0); + } break; + case MODBUS_FC_WRITE_AND_READ_REGISTERS: + case MODBUS_FC_READ_HOLDING_REGISTERS: + case MODBUS_FC_READ_INPUT_REGISTERS: + /* Header + 2 * nb values */ + length = 2 + 2 * (req[offset + 3] << 8 | req[offset + 4]); + break; + case MODBUS_FC_READ_EXCEPTION_STATUS: + length = 3; + break; + case MODBUS_FC_REPORT_SLAVE_ID: + /* The response is device specific (the header provides the + length) */ + return MSG_LENGTH_UNDEFINED; + case MODBUS_FC_MASK_WRITE_REGISTER: + length = 7; + break; + default: + length = 5; + } + + return offset + length + ctx->backend->checksum_length; +} + +/* Sends a request/response */ +static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length) +{ + int rc; + int i; + + msg_length = ctx->backend->send_msg_pre(msg, msg_length); + + if (ctx->debug) { + for (i = 0; i < msg_length; i++) + printf("[%.2X]", msg[i]); + printf("\n"); + } + + /* In recovery mode, the write command will be issued until to be + successful! Disabled by default. */ + do { + rc = ctx->backend->send(ctx, msg, msg_length); + if (rc == -1) { + _error_print(ctx, NULL); + if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) { +#ifdef _WIN32 + const int wsa_err = WSAGetLastError(); + if (wsa_err == WSAENETRESET || wsa_err == WSAENOTCONN || + wsa_err == WSAENOTSOCK || wsa_err == WSAESHUTDOWN || + wsa_err == WSAEHOSTUNREACH || wsa_err == WSAECONNABORTED || + wsa_err == WSAECONNRESET || wsa_err == WSAETIMEDOUT) { + modbus_close(ctx); + _sleep_response_timeout(ctx); + modbus_connect(ctx); + } else { + _sleep_response_timeout(ctx); + modbus_flush(ctx); + } +#else + int saved_errno = errno; + + if ((errno == EBADF || errno == ECONNRESET || errno == EPIPE)) { + modbus_close(ctx); + _sleep_response_timeout(ctx); + modbus_connect(ctx); + } else { + _sleep_response_timeout(ctx); + modbus_flush(ctx); + } + errno = saved_errno; +#endif + } + } + } while ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) && rc == -1); + + if (rc > 0 && rc != msg_length) { + errno = EMBBADDATA; + return -1; + } + + return rc; +} + +int modbus_send_raw_request(modbus_t *ctx, const uint8_t *raw_req, int raw_req_length) +{ + sft_t sft; + uint8_t req[MAX_MESSAGE_LENGTH]; + int req_length; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + if (raw_req_length < 2 || raw_req_length > (MODBUS_MAX_PDU_LENGTH + 1)) { + /* The raw request must contain function and slave at least and + must not be longer than the maximum pdu length plus the slave + address. */ + errno = EINVAL; + return -1; + } + + sft.slave = raw_req[0]; + sft.function = raw_req[1]; + /* The t_id is left to zero */ + sft.t_id = 0; + /* This response function only set the header so it's convenient here */ + req_length = ctx->backend->build_response_basis(&sft, req); + + if (raw_req_length > 2) { + /* Copy data after function code */ + memcpy(req + req_length, raw_req + 2, raw_req_length - 2); + req_length += raw_req_length - 2; + } + + return send_msg(ctx, req, req_length); +} + +/* + * ---------- Request Indication ---------- + * | Client | ---------------------->| Server | + * ---------- Confirmation Response ---------- + */ + +/* Computes the length to read after the function received */ +static uint8_t compute_meta_length_after_function(int function, msg_type_t msg_type) +{ + int length; + + if (msg_type == MSG_INDICATION) { + if (function <= MODBUS_FC_WRITE_SINGLE_REGISTER) { + length = 4; + } else if (function == MODBUS_FC_WRITE_MULTIPLE_COILS || + function == MODBUS_FC_WRITE_MULTIPLE_REGISTERS) { + length = 5; + } else if (function == MODBUS_FC_MASK_WRITE_REGISTER) { + length = 6; + } else if (function == MODBUS_FC_WRITE_AND_READ_REGISTERS) { + length = 9; + } else { + /* MODBUS_FC_READ_EXCEPTION_STATUS, MODBUS_FC_REPORT_SLAVE_ID */ + length = 0; + } + } else { + /* MSG_CONFIRMATION */ + switch (function) { + case MODBUS_FC_WRITE_SINGLE_COIL: + case MODBUS_FC_WRITE_SINGLE_REGISTER: + case MODBUS_FC_WRITE_MULTIPLE_COILS: + case MODBUS_FC_WRITE_MULTIPLE_REGISTERS: + length = 4; + break; + case MODBUS_FC_MASK_WRITE_REGISTER: + length = 6; + break; + default: + length = 1; + } + } + + return length; +} + +/* Computes the length to read after the meta information (address, count, etc) */ +static int +compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) +{ + int function = msg[ctx->backend->header_length]; + int length; + + if (msg_type == MSG_INDICATION) { + switch (function) { + case MODBUS_FC_WRITE_MULTIPLE_COILS: + case MODBUS_FC_WRITE_MULTIPLE_REGISTERS: + length = msg[ctx->backend->header_length + 5]; + break; + case MODBUS_FC_WRITE_AND_READ_REGISTERS: + length = msg[ctx->backend->header_length + 9]; + break; + default: + length = 0; + } + } else { + /* MSG_CONFIRMATION */ + if (function <= MODBUS_FC_READ_INPUT_REGISTERS || + function == MODBUS_FC_REPORT_SLAVE_ID || + function == MODBUS_FC_WRITE_AND_READ_REGISTERS) { + length = msg[ctx->backend->header_length + 1]; + } else { + length = 0; + } + } + + length += ctx->backend->checksum_length; + + return length; +} + +/* Waits a response from a modbus server or a request from a modbus client. + This function blocks if there is no replies (3 timeouts). + + The function shall return the number of received characters and the received + message in an array of uint8_t if successful. Otherwise it shall return -1 + and errno is set to one of the values defined below: + - ECONNRESET + - EMBBADDATA + - ETIMEDOUT + - read() or recv() error codes +*/ + +int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) +{ + int rc; + fd_set rset; + struct timeval tv; + struct timeval *p_tv; + unsigned int length_to_read; + int msg_length = 0; + _step_t step; +#ifdef _WIN32 + int wsa_err; +#endif + + if (ctx->debug) { + if (msg_type == MSG_INDICATION) { + printf("Waiting for an indication...\n"); + } else { + printf("Waiting for a confirmation...\n"); + } + } + + if (!ctx->backend->is_connected(ctx)) { + if (ctx->debug) { + fprintf(stderr, "ERROR The connection is not established.\n"); + } + return -1; + } + + /* Add a file descriptor to the set */ + FD_ZERO(&rset); + FD_SET(ctx->s, &rset); + + /* We need to analyse the message step by step. At the first step, we want + * to reach the function code because all packets contain this + * information. */ + step = _STEP_FUNCTION; + length_to_read = ctx->backend->header_length + 1; + + if (msg_type == MSG_INDICATION) { + /* Wait for a message, we don't know when the message will be + * received */ + if (ctx->indication_timeout.tv_sec == 0 && ctx->indication_timeout.tv_usec == 0) { + /* By default, the indication timeout isn't set */ + p_tv = NULL; + } else { + /* Wait for an indication (name of a received request by a server, see schema) + */ + tv.tv_sec = ctx->indication_timeout.tv_sec; + tv.tv_usec = ctx->indication_timeout.tv_usec; + p_tv = &tv; + } + } else { + tv.tv_sec = ctx->response_timeout.tv_sec; + tv.tv_usec = ctx->response_timeout.tv_usec; + p_tv = &tv; + } + + while (length_to_read != 0) { + rc = ctx->backend->select(ctx, &rset, p_tv, length_to_read); + if (rc == -1) { + _error_print(ctx, "select"); + if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) { +#ifdef _WIN32 + wsa_err = WSAGetLastError(); + + // no equivalent to ETIMEDOUT when select fails on Windows + if (wsa_err == WSAENETDOWN || wsa_err == WSAENOTSOCK) { + modbus_close(ctx); + modbus_connect(ctx); + } +#else + int saved_errno = errno; + + if (errno == ETIMEDOUT) { + _sleep_response_timeout(ctx); + modbus_flush(ctx); + } else if (errno == EBADF) { + modbus_close(ctx); + modbus_connect(ctx); + } + errno = saved_errno; +#endif + } + return -1; + } + + rc = ctx->backend->recv(ctx, msg + msg_length, length_to_read); + if (rc == 0) { + errno = ECONNRESET; + rc = -1; + } + + if (rc == -1) { + _error_print(ctx, "read"); +#ifdef _WIN32 + wsa_err = WSAGetLastError(); + if ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) && + (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_TCP) && + (wsa_err == WSAENOTCONN || wsa_err == WSAENETRESET || + wsa_err == WSAENOTSOCK || wsa_err == WSAESHUTDOWN || + wsa_err == WSAECONNABORTED || wsa_err == WSAETIMEDOUT || + wsa_err == WSAECONNRESET)) { + modbus_close(ctx); + modbus_connect(ctx); + } +#else + if ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) && + (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_TCP) && + (errno == ECONNRESET || errno == ECONNREFUSED || errno == EBADF)) { + int saved_errno = errno; + modbus_close(ctx); + modbus_connect(ctx); + /* Could be removed by previous calls */ + errno = saved_errno; + } +#endif + return -1; + } + + /* Display the hex code of each character received */ + if (ctx->debug) { + int i; + for (i = 0; i < rc; i++) + printf("<%.2X>", msg[msg_length + i]); + } + + /* Sums bytes received */ + msg_length += rc; + /* Computes remaining bytes */ + length_to_read -= rc; + + if (length_to_read == 0) { + switch (step) { + case _STEP_FUNCTION: + /* Function code position */ + length_to_read = compute_meta_length_after_function( + msg[ctx->backend->header_length], msg_type); + if (length_to_read != 0) { + step = _STEP_META; + break; + } /* else switches straight to the next step */ + case _STEP_META: + length_to_read = compute_data_length_after_meta(ctx, msg, msg_type); + if ((msg_length + length_to_read) > ctx->backend->max_adu_length) { + errno = EMBBADDATA; + _error_print(ctx, "too many data"); + return -1; + } + step = _STEP_DATA; + break; + default: + break; + } + } + + if (length_to_read > 0 && + (ctx->byte_timeout.tv_sec > 0 || ctx->byte_timeout.tv_usec > 0)) { + /* If there is no character in the buffer, the allowed timeout + interval between two consecutive bytes is defined by + byte_timeout */ + tv.tv_sec = ctx->byte_timeout.tv_sec; + tv.tv_usec = ctx->byte_timeout.tv_usec; + p_tv = &tv; + } + /* else timeout isn't set again, the full response must be read before + expiration of response timeout (for CONFIRMATION only) */ + } + + if (ctx->debug) + printf("\n"); + + return ctx->backend->check_integrity(ctx, msg, msg_length); +} + +/* Receive the request from a modbus master */ +int modbus_receive(modbus_t *ctx, uint8_t *req) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + return ctx->backend->receive(ctx, req); +} + +/* Receives the confirmation. + + The function shall store the read response in rsp and return the number of + values (bits or words). Otherwise, its shall return -1 and errno is set. + + The function doesn't check the confirmation is the expected response to the + initial request. +*/ +int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + return _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); +} + +static int check_confirmation(modbus_t *ctx, uint8_t *req, uint8_t *rsp, int rsp_length) +{ + int rc; + int rsp_length_computed; + const unsigned int offset = ctx->backend->header_length; + const int function = rsp[offset]; + + if (ctx->backend->pre_check_confirmation) { + rc = ctx->backend->pre_check_confirmation(ctx, req, rsp, rsp_length); + if (rc == -1) { + if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) { + _sleep_response_timeout(ctx); + modbus_flush(ctx); + } + return -1; + } + } + + rsp_length_computed = compute_response_length_from_request(ctx, req); + + /* Exception code */ + if (function >= 0x80) { + if (rsp_length == (int) (offset + 2 + ctx->backend->checksum_length) && + req[offset] == (rsp[offset] - 0x80)) { + /* Valid exception code received */ + + int exception_code = rsp[offset + 1]; + if (exception_code < MODBUS_EXCEPTION_MAX) { + errno = MODBUS_ENOBASE + exception_code; + } else { + errno = EMBBADEXC; + } + _error_print(ctx, NULL); + return -1; + } else { + errno = EMBBADEXC; + _error_print(ctx, NULL); + return -1; + } + } + + /* Check length */ + if ((rsp_length == rsp_length_computed || + rsp_length_computed == MSG_LENGTH_UNDEFINED) && + function < 0x80) { + int req_nb_value; + int rsp_nb_value; + int resp_addr_ok = TRUE; + int resp_data_ok = TRUE; + + /* Check function code */ + if (function != req[offset]) { + if (ctx->debug) { + fprintf( + stderr, + "Received function not corresponding to the request (0x%X != 0x%X)\n", + function, + req[offset]); + } + if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) { + _sleep_response_timeout(ctx); + modbus_flush(ctx); + } + errno = EMBBADDATA; + return -1; + } + + /* Check the number of values is corresponding to the request */ + switch (function) { + case MODBUS_FC_READ_COILS: + case MODBUS_FC_READ_DISCRETE_INPUTS: + /* Read functions, 8 values in a byte (nb + * of values in the request and byte count in + * the response. */ + req_nb_value = (req[offset + 3] << 8) + req[offset + 4]; + req_nb_value = (req_nb_value / 8) + ((req_nb_value % 8) ? 1 : 0); + rsp_nb_value = rsp[offset + 1]; + break; + case MODBUS_FC_WRITE_AND_READ_REGISTERS: + case MODBUS_FC_READ_HOLDING_REGISTERS: + case MODBUS_FC_READ_INPUT_REGISTERS: + /* Read functions 1 value = 2 bytes */ + req_nb_value = (req[offset + 3] << 8) + req[offset + 4]; + rsp_nb_value = (rsp[offset + 1] / 2); + break; + case MODBUS_FC_WRITE_MULTIPLE_COILS: + case MODBUS_FC_WRITE_MULTIPLE_REGISTERS: + /* address in request and response must be equal */ + if ((req[offset + 1] != rsp[offset + 1]) || + (req[offset + 2] != rsp[offset + 2])) { + resp_addr_ok = FALSE; + } + /* N Write functions */ + req_nb_value = (req[offset + 3] << 8) + req[offset + 4]; + rsp_nb_value = (rsp[offset + 3] << 8) | rsp[offset + 4]; + break; + case MODBUS_FC_REPORT_SLAVE_ID: + /* Report slave ID (bytes received) */ + req_nb_value = rsp_nb_value = rsp[offset + 1]; + break; + case MODBUS_FC_WRITE_SINGLE_COIL: + case MODBUS_FC_WRITE_SINGLE_REGISTER: + /* address in request and response must be equal */ + if ((req[offset + 1] != rsp[offset + 1]) || + (req[offset + 2] != rsp[offset + 2])) { + resp_addr_ok = FALSE; + } + /* data in request and response must be equal */ + if ((req[offset + 3] != rsp[offset + 3]) || + (req[offset + 4] != rsp[offset + 4])) { + resp_data_ok = FALSE; + } + /* 1 Write functions & others */ + req_nb_value = rsp_nb_value = 1; + break; + default: + /* 1 Write functions & others */ + req_nb_value = rsp_nb_value = 1; + break; + } + + if ((req_nb_value == rsp_nb_value) && (resp_addr_ok == TRUE) && + (resp_data_ok == TRUE)) { + rc = rsp_nb_value; + } else { + if (ctx->debug) { + fprintf(stderr, + "Received data not corresponding to the request (%d != %d)\n", + rsp_nb_value, + req_nb_value); + } + + if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) { + _sleep_response_timeout(ctx); + modbus_flush(ctx); + } + + errno = EMBBADDATA; + rc = -1; + } + } else { + if (ctx->debug) { + fprintf( + stderr, + "Message length not corresponding to the computed length (%d != %d)\n", + rsp_length, + rsp_length_computed); + } + if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) { + _sleep_response_timeout(ctx); + modbus_flush(ctx); + } + errno = EMBBADDATA; + rc = -1; + } + + return rc; +} + +static int +response_io_status(uint8_t *tab_io_status, int address, int nb, uint8_t *rsp, int offset) +{ + int shift = 0; + /* Instead of byte (not allowed in Win32) */ + int one_byte = 0; + int i; + + for (i = address; i < address + nb; i++) { + one_byte |= tab_io_status[i] << shift; + if (shift == 7) { + /* Byte is full */ + rsp[offset++] = one_byte; + one_byte = shift = 0; + } else { + shift++; + } + } + + if (shift != 0) + rsp[offset++] = one_byte; + + return offset; +} + +/* Build the exception response */ +static int response_exception(modbus_t *ctx, + sft_t *sft, + int exception_code, + uint8_t *rsp, + unsigned int to_flush, + const char *template, + ...) +{ + int rsp_length; + + /* Print debug message */ + if (ctx->debug) { + va_list ap; + + va_start(ap, template); + vfprintf(stderr, template, ap); + va_end(ap); + } + + /* Flush if required */ + if (to_flush) { + _sleep_response_timeout(ctx); + modbus_flush(ctx); + } + + /* Build exception response */ + sft->function = sft->function + 0x80; + rsp_length = ctx->backend->build_response_basis(sft, rsp); + rsp[rsp_length++] = exception_code; + + return rsp_length; +} + +/* Send a response to the received request. + Analyses the request and constructs a response. + + If an error occurs, this function construct the response + accordingly. +*/ +int modbus_reply(modbus_t *ctx, + const uint8_t *req, + int req_length, + modbus_mapping_t *mb_mapping) +{ + unsigned int offset; + int slave; + int function; + uint16_t address; + uint8_t rsp[MAX_MESSAGE_LENGTH]; + int rsp_length = 0; + sft_t sft; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + offset = ctx->backend->header_length; + slave = req[offset - 1]; + function = req[offset]; + address = (req[offset + 1] << 8) + req[offset + 2]; + + sft.slave = slave; + sft.function = function; + sft.t_id = ctx->backend->prepare_response_tid(req, &req_length); + + /* Data are flushed on illegal number of values errors. */ + switch (function) { + case MODBUS_FC_READ_COILS: + case MODBUS_FC_READ_DISCRETE_INPUTS: { + unsigned int is_input = (function == MODBUS_FC_READ_DISCRETE_INPUTS); + int start_bits = is_input ? mb_mapping->start_input_bits : mb_mapping->start_bits; + int nb_bits = is_input ? mb_mapping->nb_input_bits : mb_mapping->nb_bits; + uint8_t *tab_bits = is_input ? mb_mapping->tab_input_bits : mb_mapping->tab_bits; + const char *const name = is_input ? "read_input_bits" : "read_bits"; + int nb = (req[offset + 3] << 8) + req[offset + 4]; + /* The mapping can be shifted to reduce memory consumption and it + doesn't always start at address zero. */ + int mapping_address = address - start_bits; + + if (nb < 1 || MODBUS_MAX_READ_BITS < nb) { + rsp_length = response_exception(ctx, + &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, + rsp, + TRUE, + "Illegal nb of values %d in %s (max %d)\n", + nb, + name, + MODBUS_MAX_READ_BITS); + } else if (mapping_address < 0 || (mapping_address + nb) > nb_bits) { + rsp_length = response_exception(ctx, + &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, + rsp, + FALSE, + "Illegal data address 0x%0X in %s\n", + mapping_address < 0 ? address : address + nb, + name); + } else { + rsp_length = ctx->backend->build_response_basis(&sft, rsp); + rsp[rsp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0); + rsp_length = + response_io_status(tab_bits, mapping_address, nb, rsp, rsp_length); + } + } break; + case MODBUS_FC_READ_HOLDING_REGISTERS: + case MODBUS_FC_READ_INPUT_REGISTERS: { + unsigned int is_input = (function == MODBUS_FC_READ_INPUT_REGISTERS); + int start_registers = + is_input ? mb_mapping->start_input_registers : mb_mapping->start_registers; + int nb_registers = + is_input ? mb_mapping->nb_input_registers : mb_mapping->nb_registers; + uint16_t *tab_registers = + is_input ? mb_mapping->tab_input_registers : mb_mapping->tab_registers; + const char *const name = is_input ? "read_input_registers" : "read_registers"; + int nb = (req[offset + 3] << 8) + req[offset + 4]; + /* The mapping can be shifted to reduce memory consumption and it + doesn't always start at address zero. */ + int mapping_address = address - start_registers; + + if (nb < 1 || MODBUS_MAX_READ_REGISTERS < nb) { + rsp_length = response_exception(ctx, + &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, + rsp, + TRUE, + "Illegal nb of values %d in %s (max %d)\n", + nb, + name, + MODBUS_MAX_READ_REGISTERS); + } else if (mapping_address < 0 || (mapping_address + nb) > nb_registers) { + rsp_length = response_exception(ctx, + &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, + rsp, + FALSE, + "Illegal data address 0x%0X in %s\n", + mapping_address < 0 ? address : address + nb, + name); + } else { + int i; + + rsp_length = ctx->backend->build_response_basis(&sft, rsp); + rsp[rsp_length++] = nb << 1; + for (i = mapping_address; i < mapping_address + nb; i++) { + rsp[rsp_length++] = tab_registers[i] >> 8; + rsp[rsp_length++] = tab_registers[i] & 0xFF; + } + } + } break; + case MODBUS_FC_WRITE_SINGLE_COIL: { + int mapping_address = address - mb_mapping->start_bits; + + if (mapping_address < 0 || mapping_address >= mb_mapping->nb_bits) { + rsp_length = response_exception(ctx, + &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, + rsp, + FALSE, + "Illegal data address 0x%0X in write_bit\n", + address); + } else { + int data = (req[offset + 3] << 8) + req[offset + 4]; + + if (data == 0xFF00 || data == 0x0) { + mb_mapping->tab_bits[mapping_address] = data ? ON : OFF; + memcpy(rsp, req, req_length); + rsp_length = req_length; + } else { + rsp_length = response_exception( + ctx, + &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, + rsp, + FALSE, + "Illegal data value 0x%0X in write_bit request at address %0X\n", + data, + address); + } + } + } break; + case MODBUS_FC_WRITE_SINGLE_REGISTER: { + int mapping_address = address - mb_mapping->start_registers; + + if (mapping_address < 0 || mapping_address >= mb_mapping->nb_registers) { + rsp_length = + response_exception(ctx, + &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, + rsp, + FALSE, + "Illegal data address 0x%0X in write_register\n", + address); + } else { + int data = (req[offset + 3] << 8) + req[offset + 4]; + + mb_mapping->tab_registers[mapping_address] = data; + memcpy(rsp, req, req_length); + rsp_length = req_length; + } + } break; + case MODBUS_FC_WRITE_MULTIPLE_COILS: { + int nb = (req[offset + 3] << 8) + req[offset + 4]; + int nb_bits = req[offset + 5]; + int mapping_address = address - mb_mapping->start_bits; + + if (nb < 1 || MODBUS_MAX_WRITE_BITS < nb || nb_bits * 8 < nb) { + /* May be the indication has been truncated on reading because of + * invalid address (eg. nb is 0 but the request contains values to + * write) so it's necessary to flush. */ + rsp_length = + response_exception(ctx, + &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, + rsp, + TRUE, + "Illegal number of values %d in write_bits (max %d)\n", + nb, + MODBUS_MAX_WRITE_BITS); + } else if (mapping_address < 0 || (mapping_address + nb) > mb_mapping->nb_bits) { + rsp_length = response_exception(ctx, + &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, + rsp, + FALSE, + "Illegal data address 0x%0X in write_bits\n", + mapping_address < 0 ? address : address + nb); + } else { + /* 6 = byte count */ + modbus_set_bits_from_bytes( + mb_mapping->tab_bits, mapping_address, nb, &req[offset + 6]); + + rsp_length = ctx->backend->build_response_basis(&sft, rsp); + /* 4 to copy the bit address (2) and the quantity of bits */ + memcpy(rsp + rsp_length, req + rsp_length, 4); + rsp_length += 4; + } + } break; + case MODBUS_FC_WRITE_MULTIPLE_REGISTERS: { + int nb = (req[offset + 3] << 8) + req[offset + 4]; + int nb_bytes = req[offset + 5]; + int mapping_address = address - mb_mapping->start_registers; + + if (nb < 1 || MODBUS_MAX_WRITE_REGISTERS < nb || nb_bytes != nb * 2) { + rsp_length = response_exception( + ctx, + &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, + rsp, + TRUE, + "Illegal number of values %d in write_registers (max %d)\n", + nb, + MODBUS_MAX_WRITE_REGISTERS); + } else if (mapping_address < 0 || + (mapping_address + nb) > mb_mapping->nb_registers) { + rsp_length = + response_exception(ctx, + &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, + rsp, + FALSE, + "Illegal data address 0x%0X in write_registers\n", + mapping_address < 0 ? address : address + nb); + } else { + int i, j; + for (i = mapping_address, j = 6; i < mapping_address + nb; i++, j += 2) { + /* 6 and 7 = first value */ + mb_mapping->tab_registers[i] = + (req[offset + j] << 8) + req[offset + j + 1]; + } + + rsp_length = ctx->backend->build_response_basis(&sft, rsp); + /* 4 to copy the address (2) and the no. of registers */ + memcpy(rsp + rsp_length, req + rsp_length, 4); + rsp_length += 4; + } + } break; + case MODBUS_FC_REPORT_SLAVE_ID: { + int str_len; + int byte_count_pos; + + rsp_length = ctx->backend->build_response_basis(&sft, rsp); + /* Skip byte count for now */ + byte_count_pos = rsp_length++; + rsp[rsp_length++] = _REPORT_SLAVE_ID; + /* Run indicator status to ON */ + rsp[rsp_length++] = 0xFF; + /* LMB + length of LIBMODBUS_VERSION_STRING */ + str_len = 3 + strlen(LIBMODBUS_VERSION_STRING); + memcpy(rsp + rsp_length, "LMB" LIBMODBUS_VERSION_STRING, str_len); + rsp_length += str_len; + rsp[byte_count_pos] = rsp_length - byte_count_pos - 1; + } break; + case MODBUS_FC_READ_EXCEPTION_STATUS: + if (ctx->debug) { + fprintf(stderr, "FIXME Not implemented\n"); + } + errno = ENOPROTOOPT; + return -1; + break; + case MODBUS_FC_MASK_WRITE_REGISTER: { + int mapping_address = address - mb_mapping->start_registers; + + if (mapping_address < 0 || mapping_address >= mb_mapping->nb_registers) { + rsp_length = + response_exception(ctx, + &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, + rsp, + FALSE, + "Illegal data address 0x%0X in write_register\n", + address); + } else { + uint16_t data = mb_mapping->tab_registers[mapping_address]; + uint16_t and = (req[offset + 3] << 8) + req[offset + 4]; + uint16_t or = (req[offset + 5] << 8) + req[offset + 6]; + + data = (data & and) | (or &(~and)); + mb_mapping->tab_registers[mapping_address] = data; + memcpy(rsp, req, req_length); + rsp_length = req_length; + } + } break; + case MODBUS_FC_WRITE_AND_READ_REGISTERS: { + int nb = (req[offset + 3] << 8) + req[offset + 4]; + uint16_t address_write = (req[offset + 5] << 8) + req[offset + 6]; + int nb_write = (req[offset + 7] << 8) + req[offset + 8]; + int nb_write_bytes = req[offset + 9]; + int mapping_address = address - mb_mapping->start_registers; + int mapping_address_write = address_write - mb_mapping->start_registers; + + if (nb_write < 1 || MODBUS_MAX_WR_WRITE_REGISTERS < nb_write || nb < 1 || + MODBUS_MAX_WR_READ_REGISTERS < nb || nb_write_bytes != nb_write * 2) { + rsp_length = response_exception( + ctx, + &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, + rsp, + TRUE, + "Illegal nb of values (W%d, R%d) in write_and_read_registers (max W%d, " + "R%d)\n", + nb_write, + nb, + MODBUS_MAX_WR_WRITE_REGISTERS, + MODBUS_MAX_WR_READ_REGISTERS); + } else if (mapping_address < 0 || + (mapping_address + nb) > mb_mapping->nb_registers || + mapping_address_write < 0 || + (mapping_address_write + nb_write) > mb_mapping->nb_registers) { + rsp_length = response_exception( + ctx, + &sft, + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, + rsp, + FALSE, + "Illegal data read address 0x%0X or write address 0x%0X " + "write_and_read_registers\n", + mapping_address < 0 ? address : address + nb, + mapping_address_write < 0 ? address_write : address_write + nb_write); + } else { + int i, j; + rsp_length = ctx->backend->build_response_basis(&sft, rsp); + rsp[rsp_length++] = nb << 1; + + /* Write first. + 10 and 11 are the offset of the first values to write */ + for (i = mapping_address_write, j = 10; i < mapping_address_write + nb_write; + i++, j += 2) { + mb_mapping->tab_registers[i] = + (req[offset + j] << 8) + req[offset + j + 1]; + } + + /* and read the data for the response */ + for (i = mapping_address; i < mapping_address + nb; i++) { + rsp[rsp_length++] = mb_mapping->tab_registers[i] >> 8; + rsp[rsp_length++] = mb_mapping->tab_registers[i] & 0xFF; + } + } + } break; + + default: + rsp_length = response_exception(ctx, + &sft, + MODBUS_EXCEPTION_ILLEGAL_FUNCTION, + rsp, + TRUE, + "Unknown Modbus function code: 0x%0X\n", + function); + break; + } + + /* Suppress any responses in RTU when the request was a broadcast, excepted when quirk + * is enabled. */ + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU && + slave == MODBUS_BROADCAST_ADDRESS && + !(ctx->quirks & MODBUS_QUIRK_REPLY_TO_BROADCAST)) { + return 0; + } + return send_msg(ctx, rsp, rsp_length); +} + +int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, unsigned int exception_code) +{ + unsigned int offset; + int slave; + int function; + uint8_t rsp[MAX_MESSAGE_LENGTH]; + int rsp_length; + int dummy_length = 99; + sft_t sft; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + offset = ctx->backend->header_length; + slave = req[offset - 1]; + function = req[offset]; + + sft.slave = slave; + sft.function = function + 0x80; + sft.t_id = ctx->backend->prepare_response_tid(req, &dummy_length); + rsp_length = ctx->backend->build_response_basis(&sft, rsp); + + /* Positive exception code */ + if (exception_code < MODBUS_EXCEPTION_MAX) { + rsp[rsp_length++] = exception_code; + return send_msg(ctx, rsp, rsp_length); + } else { + errno = EINVAL; + return -1; + } +} + +/* Reads IO status */ +static int read_io_status(modbus_t *ctx, int function, int addr, int nb, uint8_t *dest) +{ + int rc; + int req_length; + + uint8_t req[_MIN_REQ_LENGTH]; + uint8_t rsp[MAX_MESSAGE_LENGTH]; + + req_length = ctx->backend->build_request_basis(ctx, function, addr, nb, req); + + rc = send_msg(ctx, req, req_length); + if (rc > 0) { + int temp, bit; + int pos = 0; + unsigned int offset; + unsigned int offset_end; + + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); + if (rc == -1) + return -1; + + rc = check_confirmation(ctx, req, rsp, rc); + if (rc == -1) + return -1; + + offset = ctx->backend->header_length + 2; + offset_end = offset + rc; + for (unsigned int i = offset; i < offset_end; i++) { + /* Shift reg hi_byte to temp */ + temp = rsp[i]; + + for (bit = 0x01; (bit & 0xff) && (pos < nb);) { + dest[pos++] = (temp & bit) ? TRUE : FALSE; + bit = bit << 1; + } + } + } + + return rc; +} + +/* Reads the boolean status of bits and sets the array elements + in the destination to TRUE or FALSE (single bits). */ +int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest) +{ + int rc; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + if (nb > MODBUS_MAX_READ_BITS) { + if (ctx->debug) { + fprintf(stderr, + "ERROR Too many bits requested (%d > %d)\n", + nb, + MODBUS_MAX_READ_BITS); + } + errno = EMBMDATA; + return -1; + } + + rc = read_io_status(ctx, MODBUS_FC_READ_COILS, addr, nb, dest); + + if (rc == -1) + return -1; + else + return nb; +} + +/* Same as modbus_read_bits but reads the remote device input table */ +int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest) +{ + int rc; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + if (nb > MODBUS_MAX_READ_BITS) { + if (ctx->debug) { + fprintf(stderr, + "ERROR Too many discrete inputs requested (%d > %d)\n", + nb, + MODBUS_MAX_READ_BITS); + } + errno = EMBMDATA; + return -1; + } + + rc = read_io_status(ctx, MODBUS_FC_READ_DISCRETE_INPUTS, addr, nb, dest); + + if (rc == -1) + return -1; + else + return nb; +} + +/* Reads the data from a remote device and put that data into an array */ +static int read_registers(modbus_t *ctx, int function, int addr, int nb, uint16_t *dest) +{ + int rc; + int req_length; + uint8_t req[_MIN_REQ_LENGTH]; + uint8_t rsp[MAX_MESSAGE_LENGTH]; + + if (nb > MODBUS_MAX_READ_REGISTERS) { + if (ctx->debug) { + fprintf(stderr, + "ERROR Too many registers requested (%d > %d)\n", + nb, + MODBUS_MAX_READ_REGISTERS); + } + errno = EMBMDATA; + return -1; + } + + req_length = ctx->backend->build_request_basis(ctx, function, addr, nb, req); + + + rc = send_msg(ctx, req, req_length); + if (rc > 0) { + unsigned int offset; + int i; + + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); + if (rc == -1) + return -1; + + rc = check_confirmation(ctx, req, rsp, rc); + if (rc == -1) + return -1; + + offset = ctx->backend->header_length; + + for (i = 0; i < rc; i++) { + /* shift reg hi_byte to temp OR with lo_byte */ + dest[i] = (rsp[offset + 2 + (i << 1)] << 8) | rsp[offset + 3 + (i << 1)]; + } + } + + return rc; +} + +/* Reads the holding registers of remote device and put the data into an + array */ +int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest) +{ + int status; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + if (nb > MODBUS_MAX_READ_REGISTERS) { + if (ctx->debug) { + fprintf(stderr, + "ERROR Too many registers requested (%d > %d)\n", + nb, + MODBUS_MAX_READ_REGISTERS); + } + errno = EMBMDATA; + return -1; + } + + status = read_registers(ctx, MODBUS_FC_READ_HOLDING_REGISTERS, addr, nb, dest); + return status; +} + +/* Reads the input registers of remote device and put the data into an array */ +int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest) +{ + int status; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + if (nb > MODBUS_MAX_READ_REGISTERS) { + fprintf(stderr, + "ERROR Too many input registers requested (%d > %d)\n", + nb, + MODBUS_MAX_READ_REGISTERS); + errno = EMBMDATA; + return -1; + } + + status = read_registers(ctx, MODBUS_FC_READ_INPUT_REGISTERS, addr, nb, dest); + + return status; +} + +/* Write a value to the specified register of the remote device. + Used by write_bit and write_register */ +static int write_single(modbus_t *ctx, int function, int addr, const uint16_t value) +{ + int rc; + int req_length; + uint8_t req[_MIN_REQ_LENGTH]; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + req_length = ctx->backend->build_request_basis(ctx, function, addr, (int) value, req); + + rc = send_msg(ctx, req, req_length); + if (rc > 0) { + /* Used by write_bit and write_register */ + uint8_t rsp[MAX_MESSAGE_LENGTH]; + + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); + if (rc == -1) + return -1; + + rc = check_confirmation(ctx, req, rsp, rc); + } + + return rc; +} + +/* Turns ON or OFF a single bit of the remote device */ +int modbus_write_bit(modbus_t *ctx, int addr, int status) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + return write_single(ctx, MODBUS_FC_WRITE_SINGLE_COIL, addr, status ? 0xFF00 : 0); +} + +/* Writes a value in one register of the remote device */ +int modbus_write_register(modbus_t *ctx, int addr, const uint16_t value) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + return write_single(ctx, MODBUS_FC_WRITE_SINGLE_REGISTER, addr, value); +} + +/* Write the bits of the array in the remote device */ +int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src) +{ + int rc; + int i; + int byte_count; + int req_length; + int bit_check = 0; + int pos = 0; + uint8_t req[MAX_MESSAGE_LENGTH]; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + if (nb > MODBUS_MAX_WRITE_BITS) { + if (ctx->debug) { + fprintf(stderr, + "ERROR Writing too many bits (%d > %d)\n", + nb, + MODBUS_MAX_WRITE_BITS); + } + errno = EMBMDATA; + return -1; + } + + req_length = ctx->backend->build_request_basis( + ctx, MODBUS_FC_WRITE_MULTIPLE_COILS, addr, nb, req); + byte_count = (nb / 8) + ((nb % 8) ? 1 : 0); + req[req_length++] = byte_count; + + for (i = 0; i < byte_count; i++) { + int bit; + + bit = 0x01; + req[req_length] = 0; + + while ((bit & 0xFF) && (bit_check++ < nb)) { + if (src[pos++]) + req[req_length] |= bit; + else + req[req_length] &= ~bit; + + bit = bit << 1; + } + req_length++; + } + + rc = send_msg(ctx, req, req_length); + if (rc > 0) { + uint8_t rsp[MAX_MESSAGE_LENGTH]; + + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); + if (rc == -1) + return -1; + + rc = check_confirmation(ctx, req, rsp, rc); + } + + return rc; +} + +/* Write the values from the array to the registers of the remote device */ +int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src) +{ + int rc; + int i; + int req_length; + int byte_count; + uint8_t req[MAX_MESSAGE_LENGTH]; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + if (nb > MODBUS_MAX_WRITE_REGISTERS) { + if (ctx->debug) { + fprintf(stderr, + "ERROR Trying to write to too many registers (%d > %d)\n", + nb, + MODBUS_MAX_WRITE_REGISTERS); + } + errno = EMBMDATA; + return -1; + } + + req_length = ctx->backend->build_request_basis( + ctx, MODBUS_FC_WRITE_MULTIPLE_REGISTERS, addr, nb, req); + byte_count = nb * 2; + req[req_length++] = byte_count; + + for (i = 0; i < nb; i++) { + req[req_length++] = src[i] >> 8; + req[req_length++] = src[i] & 0x00FF; + } + + rc = send_msg(ctx, req, req_length); + if (rc > 0) { + uint8_t rsp[MAX_MESSAGE_LENGTH]; + + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); + if (rc == -1) + return -1; + + rc = check_confirmation(ctx, req, rsp, rc); + } + + return rc; +} + +int modbus_mask_write_register(modbus_t *ctx, + int addr, + uint16_t and_mask, + uint16_t or_mask) +{ + int rc; + int req_length; + /* The request length can not exceed _MIN_REQ_LENGTH - 2 and 4 bytes to + * store the masks. The ugly substraction is there to remove the 'nb' value + * (2 bytes) which is not used. */ + uint8_t req[_MIN_REQ_LENGTH + 2]; + + req_length = ctx->backend->build_request_basis( + ctx, MODBUS_FC_MASK_WRITE_REGISTER, addr, 0, req); + + /* HACKISH, count is not used */ + req_length -= 2; + + req[req_length++] = and_mask >> 8; + req[req_length++] = and_mask & 0x00ff; + req[req_length++] = or_mask >> 8; + req[req_length++] = or_mask & 0x00ff; + + rc = send_msg(ctx, req, req_length); + if (rc > 0) { + /* Used by write_bit and write_register */ + uint8_t rsp[MAX_MESSAGE_LENGTH]; + + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); + if (rc == -1) + return -1; + + rc = check_confirmation(ctx, req, rsp, rc); + } + + return rc; +} + +/* Write multiple registers from src array to remote device and read multiple + registers from remote device to dest array. */ +int modbus_write_and_read_registers(modbus_t *ctx, + int write_addr, + int write_nb, + const uint16_t *src, + int read_addr, + int read_nb, + uint16_t *dest) + +{ + int rc; + int req_length; + int i; + int byte_count; + uint8_t req[MAX_MESSAGE_LENGTH]; + uint8_t rsp[MAX_MESSAGE_LENGTH]; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + if (write_nb > MODBUS_MAX_WR_WRITE_REGISTERS) { + if (ctx->debug) { + fprintf(stderr, + "ERROR Too many registers to write (%d > %d)\n", + write_nb, + MODBUS_MAX_WR_WRITE_REGISTERS); + } + errno = EMBMDATA; + return -1; + } + + if (read_nb > MODBUS_MAX_WR_READ_REGISTERS) { + if (ctx->debug) { + fprintf(stderr, + "ERROR Too many registers requested (%d > %d)\n", + read_nb, + MODBUS_MAX_WR_READ_REGISTERS); + } + errno = EMBMDATA; + return -1; + } + req_length = ctx->backend->build_request_basis( + ctx, MODBUS_FC_WRITE_AND_READ_REGISTERS, read_addr, read_nb, req); + + req[req_length++] = write_addr >> 8; + req[req_length++] = write_addr & 0x00ff; + req[req_length++] = write_nb >> 8; + req[req_length++] = write_nb & 0x00ff; + byte_count = write_nb * 2; + req[req_length++] = byte_count; + + for (i = 0; i < write_nb; i++) { + req[req_length++] = src[i] >> 8; + req[req_length++] = src[i] & 0x00FF; + } + + rc = send_msg(ctx, req, req_length); + if (rc > 0) { + unsigned int offset; + + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); + if (rc == -1) + return -1; + + rc = check_confirmation(ctx, req, rsp, rc); + if (rc == -1) + return -1; + + offset = ctx->backend->header_length; + for (i = 0; i < rc; i++) { + /* shift reg hi_byte to temp OR with lo_byte */ + dest[i] = (rsp[offset + 2 + (i << 1)] << 8) | rsp[offset + 3 + (i << 1)]; + } + } + + return rc; +} + +/* Send a request to get the slave ID of the device (only available in serial + communication). */ +int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest) +{ + int rc; + int req_length; + uint8_t req[_MIN_REQ_LENGTH]; + + if (ctx == NULL || max_dest <= 0) { + errno = EINVAL; + return -1; + } + + req_length = + ctx->backend->build_request_basis(ctx, MODBUS_FC_REPORT_SLAVE_ID, 0, 0, req); + + /* HACKISH, addr and count are not used */ + req_length -= 4; + + rc = send_msg(ctx, req, req_length); + if (rc > 0) { + int i; + unsigned int offset; + uint8_t rsp[MAX_MESSAGE_LENGTH]; + + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); + if (rc == -1) + return -1; + + rc = check_confirmation(ctx, req, rsp, rc); + if (rc == -1) + return -1; + + offset = ctx->backend->header_length + 2; + + /* Byte count, slave id, run indicator status and + additional data. Truncate copy to max_dest. */ + for (i = 0; i < rc && i < max_dest; i++) { + dest[i] = rsp[offset + i]; + } + } + + return rc; +} + +void _modbus_init_common(modbus_t *ctx) +{ + /* Slave and socket are initialized to -1 */ + ctx->slave = -1; + ctx->s = -1; + + ctx->debug = FALSE; + ctx->error_recovery = MODBUS_ERROR_RECOVERY_NONE; + ctx->quirks = MODBUS_QUIRK_NONE; + + ctx->response_timeout.tv_sec = 0; + ctx->response_timeout.tv_usec = _RESPONSE_TIMEOUT; + + ctx->byte_timeout.tv_sec = 0; + ctx->byte_timeout.tv_usec = _BYTE_TIMEOUT; + + ctx->indication_timeout.tv_sec = 0; + ctx->indication_timeout.tv_usec = 0; +} + +/* Define the slave number */ +int modbus_set_slave(modbus_t *ctx, int slave) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + return ctx->backend->set_slave(ctx, slave); +} + +int modbus_get_slave(modbus_t *ctx) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + return ctx->slave; +} + +int modbus_set_error_recovery(modbus_t *ctx, modbus_error_recovery_mode error_recovery) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + /* The type of modbus_error_recovery_mode is unsigned enum */ + ctx->error_recovery = (uint8_t) error_recovery; + return 0; +} + +// FIXME Doesn't work under Windows RTU +int modbus_set_socket(modbus_t *ctx, int s) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + ctx->s = s; + return 0; +} + +int modbus_get_socket(modbus_t *ctx) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + return ctx->s; +} + +/* Get the timeout interval used to wait for a response */ +int modbus_get_response_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + *to_sec = ctx->response_timeout.tv_sec; + *to_usec = ctx->response_timeout.tv_usec; + return 0; +} + +int modbus_set_response_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec) +{ + if (ctx == NULL || (to_sec == 0 && to_usec == 0) || to_usec > 999999) { + errno = EINVAL; + return -1; + } + + ctx->response_timeout.tv_sec = to_sec; + ctx->response_timeout.tv_usec = to_usec; + return 0; +} + +/* Get the timeout interval between two consecutive bytes of a message */ +int modbus_get_byte_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + *to_sec = ctx->byte_timeout.tv_sec; + *to_usec = ctx->byte_timeout.tv_usec; + return 0; +} + +int modbus_set_byte_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec) +{ + /* Byte timeout can be disabled when both values are zero */ + if (ctx == NULL || to_usec > 999999) { + errno = EINVAL; + return -1; + } + + ctx->byte_timeout.tv_sec = to_sec; + ctx->byte_timeout.tv_usec = to_usec; + return 0; +} + +/* Get the timeout interval used by the server to wait for an indication from a client */ +int modbus_get_indication_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + *to_sec = ctx->indication_timeout.tv_sec; + *to_usec = ctx->indication_timeout.tv_usec; + return 0; +} + +int modbus_set_indication_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec) +{ + /* Indication timeout can be disabled when both values are zero */ + if (ctx == NULL || to_usec > 999999) { + errno = EINVAL; + return -1; + } + + ctx->indication_timeout.tv_sec = to_sec; + ctx->indication_timeout.tv_usec = to_usec; + return 0; +} + +int modbus_get_header_length(modbus_t *ctx) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + return ctx->backend->header_length; +} + +int modbus_enable_quirks(modbus_t *ctx, unsigned int quirks_mask) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + /* Enable quirks that have a true value at their index in the mask */ + ctx->quirks |= quirks_mask; + return 0; +} + +int modbus_disable_quirks(modbus_t *ctx, unsigned int quirks_mask) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + /* Disable quirks that have a true value at ther index in the mask */ + ctx->quirks &= ~quirks_mask; + return 0; +} + +int modbus_connect(modbus_t *ctx) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + return ctx->backend->connect(ctx); +} + +void modbus_close(modbus_t *ctx) +{ + if (ctx == NULL) + return; + + ctx->backend->close(ctx); +} + +void modbus_free(modbus_t *ctx) +{ + if (ctx == NULL) + return; + + ctx->backend->free(ctx); +} + +int modbus_set_debug(modbus_t *ctx, int flag) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + ctx->debug = flag; + return 0; +} + +/* Allocates 4 arrays to store bits, input bits, registers and inputs + registers. The pointers are stored in modbus_mapping structure. + + The modbus_mapping_new_start_address() function shall return the new allocated + structure if successful. Otherwise it shall return NULL and set errno to + ENOMEM. */ +modbus_mapping_t *modbus_mapping_new_start_address(unsigned int start_bits, + unsigned int nb_bits, + unsigned int start_input_bits, + unsigned int nb_input_bits, + unsigned int start_registers, + unsigned int nb_registers, + unsigned int start_input_registers, + unsigned int nb_input_registers) +{ + modbus_mapping_t *mb_mapping; + + mb_mapping = (modbus_mapping_t *) malloc(sizeof(modbus_mapping_t)); + if (mb_mapping == NULL) { + return NULL; + } + + /* 0X */ + mb_mapping->nb_bits = nb_bits; + mb_mapping->start_bits = start_bits; + if (nb_bits == 0) { + mb_mapping->tab_bits = NULL; + } else { + /* Negative number raises a POSIX error */ + mb_mapping->tab_bits = (uint8_t *) malloc(nb_bits * sizeof(uint8_t)); + if (mb_mapping->tab_bits == NULL) { + free(mb_mapping); + return NULL; + } + memset(mb_mapping->tab_bits, 0, nb_bits * sizeof(uint8_t)); + } + + /* 1X */ + mb_mapping->nb_input_bits = nb_input_bits; + mb_mapping->start_input_bits = start_input_bits; + if (nb_input_bits == 0) { + mb_mapping->tab_input_bits = NULL; + } else { + mb_mapping->tab_input_bits = (uint8_t *) malloc(nb_input_bits * sizeof(uint8_t)); + if (mb_mapping->tab_input_bits == NULL) { + free(mb_mapping->tab_bits); + free(mb_mapping); + return NULL; + } + memset(mb_mapping->tab_input_bits, 0, nb_input_bits * sizeof(uint8_t)); + } + + /* 4X */ + mb_mapping->nb_registers = nb_registers; + mb_mapping->start_registers = start_registers; + if (nb_registers == 0) { + mb_mapping->tab_registers = NULL; + } else { + mb_mapping->tab_registers = (uint16_t *) malloc(nb_registers * sizeof(uint16_t)); + if (mb_mapping->tab_registers == NULL) { + free(mb_mapping->tab_input_bits); + free(mb_mapping->tab_bits); + free(mb_mapping); + return NULL; + } + memset(mb_mapping->tab_registers, 0, nb_registers * sizeof(uint16_t)); + } + + /* 3X */ + mb_mapping->nb_input_registers = nb_input_registers; + mb_mapping->start_input_registers = start_input_registers; + if (nb_input_registers == 0) { + mb_mapping->tab_input_registers = NULL; + } else { + mb_mapping->tab_input_registers = + (uint16_t *) malloc(nb_input_registers * sizeof(uint16_t)); + if (mb_mapping->tab_input_registers == NULL) { + free(mb_mapping->tab_registers); + free(mb_mapping->tab_input_bits); + free(mb_mapping->tab_bits); + free(mb_mapping); + return NULL; + } + memset(mb_mapping->tab_input_registers, 0, nb_input_registers * sizeof(uint16_t)); + } + + return mb_mapping; +} + +modbus_mapping_t *modbus_mapping_new(int nb_bits, + int nb_input_bits, + int nb_registers, + int nb_input_registers) +{ + return modbus_mapping_new_start_address( + 0, nb_bits, 0, nb_input_bits, 0, nb_registers, 0, nb_input_registers); +} + +/* Frees the 4 arrays */ +void modbus_mapping_free(modbus_mapping_t *mb_mapping) +{ + if (mb_mapping == NULL) { + return; + } + + free(mb_mapping->tab_input_registers); + free(mb_mapping->tab_registers); + free(mb_mapping->tab_input_bits); + free(mb_mapping->tab_bits); + free(mb_mapping); +} + +#ifndef HAVE_STRLCPY +/* + * Function strlcpy was originally developed by + * Todd C. Miller to simplify writing secure code. + * See ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3 + * for more information. + * + * Thank you Ulrich Drepper... not! + * + * Copy src to string dest of size dest_size. At most dest_size-1 characters + * will be copied. Always NUL terminates (unless dest_size == 0). Returns + * strlen(src); if retval >= dest_size, truncation occurred. + */ +size_t strlcpy(char *dest, const char *src, size_t dest_size) +{ + register char *d = dest; + register const char *s = src; + register size_t n = dest_size; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dest, add NUL and traverse rest of src */ + if (n == 0) { + if (dest_size != 0) + *d = '\0'; /* NUL-terminate dest */ + while (*s++) + ; + } + + return (s - src - 1); /* count does not include NUL */ +} +#endif diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..9089f22 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,11 @@ +#include + +#include "modbus.h" +#include "dtu.h" + +int main() { + std::string deviceAddress{"/dev/ttyUSB0"}; + Dtu dtu{ deviceAddress.c_str() }; + + return 0; +} \ No newline at end of file