diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 00000000..ea53e438
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,62 @@
+name: Test
+
+# Run this job on all pushes and pull requests
+# as well as tags with a semantic version
+on:
+ push:
+ branches:
+ - '*'
+ pull_request: {}
+
+jobs:
+
+ # Runs lib tests on all supported node versions and OSes
+ build-and-test:
+ if: contains(github.event.head_commit.message, '[skip ci]') == false
+
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os: [ubuntu-latest, macos-latest, windows-2019]
+
+ steps:
+ - uses: actions/checkout@v1
+
+ - name: Install automake (macos)
+ if: startsWith(runner.OS, 'macOS')
+ run: brew install automake
+
+ - name: Build (Linux/macOS)
+ if: startsWith(runner.OS, 'linux') || startsWith(runner.OS, 'macOS')
+ run: ./build.sh
+
+ - name: Prepare Windows build
+ if: startsWith(runner.OS, 'Windows')
+ uses: microsoft/setup-msbuild@v1.1
+
+ - name: Install Windows 8.1 SDK
+ if: startsWith(runner.OS, 'Windows')
+ shell: powershell
+ run: |
+ Invoke-WebRequest -Method Get -Uri https://go.microsoft.com/fwlink/p/?LinkId=323507 -OutFile sdksetup.exe -UseBasicParsing
+ Start-Process -Wait sdksetup.exe -ArgumentList "/q", "/norestart", "/features", "OptionId.WindowsDesktopSoftwareDevelopmentKit", "OptionId.NetFxSoftwareDevelopmentKit"
+
+ - name: Build (Windows)
+ if: startsWith(runner.OS, 'Windows')
+ run: msbuild libmbus.vcxproj -t:rebuild -verbosity:diag -property:Configuration=Release
+
+ - name: Build tests
+ if: startsWith(runner.OS, 'linux') || startsWith(runner.OS, 'macOS')
+ run: cd test && make
+
+ - name: Test Success Frames
+ if: startsWith(runner.OS, 'linux') || startsWith(runner.OS, 'macOS')
+ run: cd test && ./generate-xml.sh test-frames
+
+ - name: Test Error Frames
+ if: startsWith(runner.OS, 'linux') || startsWith(runner.OS, 'macOS')
+ run: cd test && ./generate-xml.sh error-frames || true
+
+ - name: Test Unsupported Frames
+ if: startsWith(runner.OS, 'linux') || startsWith(runner.OS, 'macOS')
+ run: cd test && ./generate-xml.sh unsupported-frames || true
diff --git a/.gitignore b/.gitignore
index 1136a1aa..2306a166 100644
--- a/.gitignore
+++ b/.gitignore
@@ -73,7 +73,10 @@ test/unsupported-frames/*.xml.new
/build/
_build/
+/Debug/
+/Release/
# IDE
/.vscode/
-CMakeLists.txt.user
\ No newline at end of file
+/.vs/
+CMakeLists.txt.user
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 70b00795..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-language: c
-
-compiler:
- - gcc
- - clang
-
-os:
- - linux
- - osx
-
-script:
- - ./build.sh
- - cd test && make && ./generate-xml.sh test-frames
- - cd test && make && ./generate-xml.sh test/error-frames || true
- - cd test && make && ./generate-xml.sh test/unsupported-frames || true
diff --git a/WINDOWS_TODO.md b/WINDOWS_TODO.md
new file mode 100644
index 00000000..004a5eec
--- /dev/null
+++ b/WINDOWS_TODO.md
@@ -0,0 +1,9 @@
+# Status Windows Build
+
+## What's working
+* Build mbus library including tcp and serial support on Windows using Visual Studio in 32bit and 64bit
+
+## Todo
+* add correct build configuration (complete vcxproj file?)
+* check all binaries for needed changes for windows Build
+* implement test shellscript as bat file for Windows
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 00000000..2614f129
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,11 @@
+version: 'test-{build}'
+platform:
+ - x86
+ - x64
+configuration:
+ - Debug
+ - Release
+clone_folder: 'c:\projects\%APPVEYOR_PROJECT_NAME%'
+build: MSBuild
+test_script:
+ - echo %cd%
diff --git a/libmbus.vcxproj b/libmbus.vcxproj
new file mode 100644
index 00000000..e25bce3b
--- /dev/null
+++ b/libmbus.vcxproj
@@ -0,0 +1,256 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ Release
+ Debug
+
+
+ {B03220E0-285E-8766-5959-75355F21213E}
+ Win32Proj
+ libmbus
+ true
+ x64
+ libmbus
+ 10.0
+
+
+
+ StaticLibrary
+
+
+ v142
+
+
+
+
+
+
+
+
+
+ $(ExecutablePath);$(MSBuildProjectDirectory)\..\bin\;$(MSBuildProjectDirectory)\..\bin\
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+ false
+ true
+ false
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ $(ProjectName)
+ $(OutDir)\$(ProjectName)$(TargetExt)
+
+
+
+ %(AdditionalIncludeDirectories)
+ EnableFastChecks
+ true
+ false
+ ProgramDatabase
+ 4267;4351;4355;4800;4251;%(DisableSpecificWarnings)
+ false
+ false
+ false
+ Disabled
+ NotUsing
+ USING_UV_SHARED=1;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;DEBUG;_DEBUG;%(PreprocessorDefinitions)
+ MultiThreadedDebug
+ true
+ true
+ false
+ Level3
+
+
+ $(OutDir)$(ProjectName)$(TargetExt)
+
+
+
+
+ /ignore:4199 %(AdditionalOptions)
+ true
+ true
+ %(DelayLoadDLLs)
+ true
+ true
+ true
+ true
+ true
+ MachineX86
+
+
+ .\mbus;%(AdditionalIncludeDirectories)
+ USING_UV_SHARED=1;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;DEBUG;_DEBUG;%(PreprocessorDefinitions);%(PreprocessorDefinitions)
+
+
+
+
+ %(AdditionalIncludeDirectories)
+ /MP %(AdditionalOptions)
+ true
+ false
+ ProgramDatabase
+ 4267;4351;4355;4800;4251;%(DisableSpecificWarnings)
+ false
+ Speed
+ true
+ AnySuitable
+ true
+ true
+ Full
+ NotUsing
+ USING_UV_SHARED=1;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)
+ MultiThreaded
+ false
+ true
+ true
+ false
+ Level3
+ true
+
+
+ /LTCG %(AdditionalOptions)
+ $(OutDir)$(ProjectName)$(TargetExt)
+
+
+
+
+ /ignore:4199 %(AdditionalOptions)
+ true
+ true
+ %(DelayLoadDLLs)
+ true
+ true
+ true
+ UseLinkTimeCodeGeneration
+ true
+ true
+ true
+ true
+ MachineX86
+
+
+ .\mbus;%(AdditionalIncludeDirectories)
+ USING_UV_SHARED=1;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions);%(PreprocessorDefinitions)
+
+
+
+
+ %(AdditionalIncludeDirectories)
+ EnableFastChecks
+ true
+ false
+ ProgramDatabase
+ 4267;4351;4355;4800;4251;%(DisableSpecificWarnings)
+ false
+ false
+ false
+ Disabled
+ NotUsing
+ USING_UV_SHARED=1;WIN64;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;DEBUG;_DEBUG;%(PreprocessorDefinitions)
+ MultiThreadedDebug
+ true
+ true
+ false
+ Level3
+
+
+ $(OutDir)$(ProjectName)$(TargetExt)
+
+
+
+
+ /ignore:4199 %(AdditionalOptions)
+ true
+ true
+ %(DelayLoadDLLs)
+ true
+ true
+ true
+ true
+ true
+ MachineX86
+
+
+ .\mbus;%(AdditionalIncludeDirectories)
+ USING_UV_SHARED=1;WIN32;WIN64;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;DEBUG;_DEBUG;%(PreprocessorDefinitions);%(PreprocessorDefinitions)
+
+
+
+
+ %(AdditionalIncludeDirectories)
+ /MP %(AdditionalOptions)
+ true
+ false
+ ProgramDatabase
+ 4267;4351;4355;4800;4251;%(DisableSpecificWarnings)
+ false
+ Speed
+ true
+ AnySuitable
+ true
+ true
+ Full
+ NotUsing
+ USING_UV_SHARED=1;WIN32;WIN64;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)
+ MultiThreaded
+ false
+ true
+ true
+ false
+ Level3
+ true
+
+
+ /LTCG %(AdditionalOptions)
+ $(OutDir)$(ProjectName)$(TargetExt)
+
+
+
+
+ /ignore:4199 %(AdditionalOptions)
+ true
+ true
+ %(DelayLoadDLLs)
+ true
+ true
+ true
+ UseLinkTimeCodeGeneration
+ true
+ true
+ true
+ true
+ MachineX86
+
+
+ .\mbus;%(AdditionalIncludeDirectories)
+ USING_UV_SHARED=1;WIN32;WIN64;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions);%(PreprocessorDefinitions)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mbus-serial-request-data-multi-reply.vcxproj b/mbus-serial-request-data-multi-reply.vcxproj
new file mode 100644
index 00000000..7d49dc42
--- /dev/null
+++ b/mbus-serial-request-data-multi-reply.vcxproj
@@ -0,0 +1,167 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+ 16.0
+ Win32Proj
+ {C4D9D19C-C88D-446D-B14A-57F0C5487A59}
+ mbus_serial_request_data_multi_reply
+ 10.0
+
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+ false
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+
+
+ false
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ true
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ true
+ true
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mbus-serial-request-data.vcxproj b/mbus-serial-request-data.vcxproj
new file mode 100644
index 00000000..6d888426
--- /dev/null
+++ b/mbus-serial-request-data.vcxproj
@@ -0,0 +1,167 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+ 16.0
+ Win32Proj
+ {4551e229-8923-4561-8748-6d2d0c27ee3e}
+ mbus_serial_request_data
+ 10.0
+
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+ false
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+
+
+ false
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ true
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ true
+ true
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mbus-serial-scan-secondary.vcxproj b/mbus-serial-scan-secondary.vcxproj
new file mode 100644
index 00000000..63994096
--- /dev/null
+++ b/mbus-serial-scan-secondary.vcxproj
@@ -0,0 +1,167 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {3F6C7EC7-BA56-4A11-9551-1D5DDCB272DE}
+ mbusserialscansecondary
+ 10.0
+
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+ false
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+
+
+ false
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ true
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ true
+ true
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mbus-serial-scan.vcxproj b/mbus-serial-scan.vcxproj
new file mode 100644
index 00000000..3fb0667c
--- /dev/null
+++ b/mbus-serial-scan.vcxproj
@@ -0,0 +1,167 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {1fb54c4e-350c-4ba5-9892-80ec3fd95c94}
+ mbusserialscan
+ 10.0
+
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+ false
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+
+
+ false
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ true
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ true
+ true
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mbus-serial-select-secondary.vcxproj b/mbus-serial-select-secondary.vcxproj
new file mode 100644
index 00000000..f0960b8b
--- /dev/null
+++ b/mbus-serial-select-secondary.vcxproj
@@ -0,0 +1,167 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {8E02C033-2D69-49A4-B0AD-756FF4063F7C}
+ mbusserialselectsecondary
+ 10.0
+
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+ false
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+
+
+ false
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ true
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ true
+ true
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mbus-serial-set-address.vcxproj b/mbus-serial-set-address.vcxproj
new file mode 100644
index 00000000..c3a6e3db
--- /dev/null
+++ b/mbus-serial-set-address.vcxproj
@@ -0,0 +1,167 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {6327DE5C-FA2D-409E-8AA2-8E3806C3F4D7}
+ mbusserialsetaddress
+ 10.0
+
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+ false
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+
+
+ false
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ true
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ true
+ true
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mbus-serial-switch-baudrate.vcxproj b/mbus-serial-switch-baudrate.vcxproj
new file mode 100644
index 00000000..c8513122
--- /dev/null
+++ b/mbus-serial-switch-baudrate.vcxproj
@@ -0,0 +1,167 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {5BAFA825-7CF6-40BC-A4A3-C30CDC878F9A}
+ mbusserialswitchbaudrate
+ 10.0
+
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+ false
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+
+
+ false
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ $(Configuration)\obj\$(ProjectName)\$(Platform)\
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ true
+ true
+ $(SolutionDir)$(Configuration)\$(Platform)\
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)
+
+
+ Console
+ true
+ true
+ true
+ libmbus.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Configuration)\$(Platform)\
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mbus/mbus-protocol-aux.c b/mbus/mbus-protocol-aux.c
index 60b5fa66..903dcfbc 100755
--- a/mbus/mbus-protocol-aux.c
+++ b/mbus/mbus-protocol-aux.c
@@ -10,6 +10,9 @@
// Large parts of this file was contributed by Tomas Menzl.
//
//------------------------------------------------------------------------------
+#ifdef _WIN32
+#define __PRETTY_FUNCTION__ __FUNCSIG__
+#endif
#include "mbus-protocol-aux.h"
#include "mbus-serial.h"
@@ -1924,6 +1927,42 @@ mbus_send_request_frame(mbus_handle * handle, int address)
return retval;
}
+//------------------------------------------------------------------------------
+// send a request packet to from master to slave
+//------------------------------------------------------------------------------
+int
+mbus_send_request_frame_fcb(mbus_handle * handle, int address)
+{
+ int retval = 0;
+ mbus_frame *frame;
+
+ if (mbus_is_primary_address(address) == 0)
+ {
+ MBUS_ERROR("%s: invalid address %d\n", __PRETTY_FUNCTION__, address);
+ return -1;
+ }
+
+ frame = mbus_frame_new(MBUS_FRAME_TYPE_SHORT);
+
+ if (frame == NULL)
+ {
+ MBUS_ERROR("%s: failed to allocate mbus frame.\n", __PRETTY_FUNCTION__);
+ return -1;
+ }
+
+ frame->control = MBUS_CONTROL_MASK_REQ_UD2 | MBUS_CONTROL_MASK_DIR_M2S | MBUS_CONTROL_MASK_FCB;
+ frame->address = address;
+
+ if (mbus_send_frame(handle, frame) == -1)
+ {
+ MBUS_ERROR("%s: failed to send mbus frame.\n", __PRETTY_FUNCTION__);
+ retval = -1;
+ }
+
+ mbus_frame_free(frame);
+ return retval;
+}
+
//------------------------------------------------------------------------------
// send a user data packet from master to slave
//------------------------------------------------------------------------------
@@ -2216,7 +2255,7 @@ mbus_send_ping_frame(mbus_handle *handle, int address, char purge_response)
int
mbus_select_secondary_address(mbus_handle * handle, const char *mask)
{
- int ret;
+ int ret, frameType;
mbus_frame reply;
if (mask == NULL || strlen(mask) != 16)
@@ -2249,7 +2288,7 @@ mbus_select_secondary_address(mbus_handle * handle, const char *mask)
return MBUS_PROBE_COLLISION;
}
- if (mbus_frame_type(&reply) == MBUS_FRAME_TYPE_ACK)
+ if (frameType = mbus_frame_type(&reply) == MBUS_FRAME_TYPE_ACK)
{
/* check for more data (collision) */
if (mbus_purge_frames(handle))
@@ -2260,7 +2299,7 @@ mbus_select_secondary_address(mbus_handle * handle, const char *mask)
return MBUS_PROBE_SINGLE;
}
- MBUS_ERROR("%s: Unexpected reply for address [%s].\n", __PRETTY_FUNCTION__, mask);
+ MBUS_ERROR("%s: Unexpected reply for address [%s]. ret=%d, frameType=%d\n", __PRETTY_FUNCTION__, mask, ret, frameType);
return MBUS_PROBE_NOTHING;
}
diff --git a/mbus/mbus-protocol-aux.h b/mbus/mbus-protocol-aux.h
index 4dacef4c..9b97b070 100755
--- a/mbus/mbus-protocol-aux.h
+++ b/mbus/mbus-protocol-aux.h
@@ -97,7 +97,7 @@ typedef struct _mbus_handle {
void (*recv_event) (unsigned char src_type, const char *buff, size_t len);
void (*send_event) (unsigned char src_type, const char *buff, size_t len);
void (*scan_progress) (struct _mbus_handle *handle, const char *mask);
- void (*found_event) (struct _mbus_handle *handle, mbus_frame *frame);
+ void (*found_event) (struct _mbus_handle *handle, mbus_frame *frame);
void *auxdata;
} mbus_handle;
@@ -294,6 +294,7 @@ int mbus_send_switch_baudrate_frame(mbus_handle * handle, int address, long baud
* @return Zero when successful.
*/
int mbus_send_request_frame(mbus_handle * handle, int address);
+int mbus_send_request_frame_fcb(mbus_handle * handle, int address);
/**
* Sends user data frame (SND_UD) to given slave using "unified" handle
diff --git a/mbus/mbus-protocol.c b/mbus/mbus-protocol.c
index b9b66b3b..6aebed1d 100755
--- a/mbus/mbus-protocol.c
+++ b/mbus/mbus-protocol.c
@@ -8,6 +8,11 @@
//
//------------------------------------------------------------------------------
+#ifdef _WIN32
+#define __PRETTY_FUNCTION__ __FUNCSIG__
+#endif
+
+
#include
#include
#include
@@ -3289,8 +3294,16 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x09: // 2 digit BCD (8 bit)
- int_val = (int)mbus_data_bcd_decode_hex(record->data, 1);
- snprintf(buff, sizeof(buff), "%X", int_val);
+ if ((record->drh.dib.dif & MBUS_DATA_RECORD_DIF_MASK_FUNCTION) == 0x30)
+ {
+ int_val = (int)mbus_data_bcd_decode_hex(record->data, 1);
+ snprintf(buff, sizeof(buff), "%X", int_val);
+ }
+ else
+ {
+ int_val = (int)mbus_data_bcd_decode(record->data, 1);
+ snprintf(buff, sizeof(buff), "%d", int_val);
+ }
if (debug)
printf("%s: DIF 0x%.2x was decoded using 2 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@@ -3299,8 +3312,16 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x0A: // 4 digit BCD (16 bit)
- int_val = (int)mbus_data_bcd_decode_hex(record->data, 2);
- snprintf(buff, sizeof(buff), "%X", int_val);
+ if ((record->drh.dib.dif & MBUS_DATA_RECORD_DIF_MASK_FUNCTION) == 0x30)
+ {
+ int_val = (int)mbus_data_bcd_decode_hex(record->data, 2);
+ snprintf(buff, sizeof(buff), "%X", int_val);
+ }
+ else
+ {
+ int_val = (int)mbus_data_bcd_decode(record->data, 2);
+ snprintf(buff, sizeof(buff), "%d", int_val);
+ }
if (debug)
printf("%s: DIF 0x%.2x was decoded using 4 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@@ -3309,8 +3330,16 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x0B: // 6 digit BCD (24 bit)
- int_val = (int)mbus_data_bcd_decode_hex(record->data, 3);
- snprintf(buff, sizeof(buff), "%X", int_val);
+ if ((record->drh.dib.dif & MBUS_DATA_RECORD_DIF_MASK_FUNCTION) == 0x30)
+ {
+ int_val = (int)mbus_data_bcd_decode_hex(record->data, 3);
+ snprintf(buff, sizeof(buff), "%X", int_val);
+ }
+ else
+ {
+ int_val = (int)mbus_data_bcd_decode(record->data, 3);
+ snprintf(buff, sizeof(buff), "%d", int_val);
+ }
if (debug)
printf("%s: DIF 0x%.2x was decoded using 6 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@@ -3319,8 +3348,16 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x0C: // 8 digit BCD (32 bit)
- int_val = (int)mbus_data_bcd_decode_hex(record->data, 4);
- snprintf(buff, sizeof(buff), "%X", int_val);
+ if ((record->drh.dib.dif & MBUS_DATA_RECORD_DIF_MASK_FUNCTION) == 0x30)
+ {
+ int_val = (int)mbus_data_bcd_decode_hex(record->data, 4);
+ snprintf(buff, sizeof(buff), "%X", int_val);
+ }
+ else
+ {
+ int_val = (int)mbus_data_bcd_decode(record->data, 4);
+ snprintf(buff, sizeof(buff), "%d", int_val);
+ }
if (debug)
printf("%s: DIF 0x%.2x was decoded using 8 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
@@ -3329,8 +3366,16 @@ mbus_data_record_decode(mbus_data_record *record)
case 0x0E: // 12 digit BCD (48 bit)
- long_long_val = mbus_data_bcd_decode_hex(record->data, 6);
- snprintf(buff, sizeof(buff), "%llX", long_long_val);
+ if ((record->drh.dib.dif & MBUS_DATA_RECORD_DIF_MASK_FUNCTION) == 0x30)
+ {
+ long_long_val = mbus_data_bcd_decode_hex(record->data, 6);
+ snprintf(buff, sizeof(buff), "%llX", long_long_val);
+ }
+ else
+ {
+ long_long_val = mbus_data_bcd_decode(record->data, 6);
+ snprintf(buff, sizeof(buff), "%lld", long_long_val);
+ }
if (debug)
printf("%s: DIF 0x%.2x was decoded using 12 digit BCD\n", __PRETTY_FUNCTION__, record->drh.dib.dif);
diff --git a/mbus/mbus-serial.c b/mbus/mbus-serial.c
index 5a2a3f3b..cc4b3431 100755
--- a/mbus/mbus-serial.c
+++ b/mbus/mbus-serial.c
@@ -8,18 +8,46 @@
//
//------------------------------------------------------------------------------
+#ifdef _WIN32
+#define __PRETTY_FUNCTION__ __FUNCSIG__
+#endif
+
+#define MBUS_ERROR(...) fprintf (stderr, __VA_ARGS__)
+#ifdef DEBUG
+#define MBUS_SERIAL_DEBUG
+#endif
+
+#ifdef _WIN32
+#include
+
+#include
+typedef SSIZE_T ssize_t;
+
+#ifndef SSIZE_MAX
+#ifdef _WIN64
+#define SSIZE_MAX _I64_MAX
+#else
+#define SSIZE_MAX LONG_MAX
+#endif
+
+#endif
+
+#define O_NOCTTY 0x0000 // No idea if this makes sense
+
+#else
#include
+#include
+#include
+#endif
+
#include
#include
#include
#include
-#include
-#include
#include
-#include
#include "mbus-serial.h"
#include "mbus-protocol-aux.h"
@@ -27,6 +55,14 @@
#define PACKET_BUFF_SIZE 2048
+#ifdef _WIN32
+#define read(...) readFromSerial(__VA_ARGS__)
+#define write(...) writeToSerial(__VA_ARGS__)
+#define select(...) selectSerial(__VA_ARGS__)
+#define open(...) openSerial(__VA_ARGS__)
+#define close(...) closeSerial(__VA_ARGS__)
+#endif
+
//------------------------------------------------------------------------------
/// Set up a serial connection handle.
//------------------------------------------------------------------------------
@@ -53,7 +89,7 @@ mbus_serial_connect(mbus_handle *handle)
// Use blocking read and handle it by serial port VMIN/VTIME setting
if ((handle->fd = open(device, O_RDWR | O_NOCTTY)) < 0)
{
- fprintf(stderr, "%s: failed to open tty.", __PRETTY_FUNCTION__);
+ fprintf(stderr, "%s: failed to open tty.\n", __PRETTY_FUNCTION__);
return -1;
}
@@ -193,7 +229,7 @@ mbus_serial_disconnect(mbus_handle *handle)
if (handle->fd < 0)
{
- return -1;
+ return -1;
}
close(handle->fd);
@@ -216,7 +252,10 @@ mbus_serial_data_free(mbus_handle *handle)
return;
}
- free(serial_data->device);
+ //if (serial_data->device != NULL)
+ //{
+ free(serial_data->device);
+ //}
free(serial_data);
handle->auxdata = NULL;
}
@@ -239,6 +278,7 @@ mbus_serial_send_frame(mbus_handle *handle, mbus_frame *frame)
// Make sure serial connection is open
if (isatty(handle->fd) == 0)
{
+ MBUS_ERROR("%s: connection not open\n", __PRETTY_FUNCTION__);
return -1;
}
@@ -287,7 +327,7 @@ mbus_serial_send_frame(mbus_handle *handle, mbus_frame *frame)
int
mbus_serial_recv_frame(mbus_handle *handle, mbus_frame *frame)
{
- char buff[PACKET_BUFF_SIZE];
+ unsigned char buff[PACKET_BUFF_SIZE];
int remaining, timeouts;
ssize_t len, nread;
@@ -298,7 +338,11 @@ mbus_serial_recv_frame(mbus_handle *handle, mbus_frame *frame)
}
// Make sure serial connection is open
+ #ifdef _WIN32
+ if (GetFileType(getHandle()) != FILE_TYPE_CHAR )
+ #else
if (isatty(handle->fd) == 0)
+ #endif
{
fprintf(stderr, "%s: Serial connection is not available.\n", __PRETTY_FUNCTION__);
return MBUS_RECV_RESULT_ERROR;
@@ -320,7 +364,9 @@ mbus_serial_recv_frame(mbus_handle *handle, mbus_frame *frame)
return MBUS_RECV_RESULT_ERROR;
}
- //printf("%s: Attempt to read %d bytes [len = %d]\n", __PRETTY_FUNCTION__, remaining, len);
+ #ifdef MBUS_SERIAL_DEBUG
+ printf("%s: Attempt to read %d bytes [len = %d]\n", __PRETTY_FUNCTION__, remaining, len);
+ #endif
if ((nread = read(handle->fd, &buff[len], remaining)) == -1)
{
@@ -329,7 +375,15 @@ mbus_serial_recv_frame(mbus_handle *handle, mbus_frame *frame)
return MBUS_RECV_RESULT_ERROR;
}
-// printf("%s: Got %d byte [remaining %d, len %d]\n", __PRETTY_FUNCTION__, nread, remaining, len);
+ #ifdef MBUS_SERIAL_DEBUG
+ printf("%s: Got %d byte [remaining %d, len %d]\n", __PRETTY_FUNCTION__, nread, remaining, len);
+ int i;
+ for (i = len; i < len+nread; i++)
+ {
+ printf("%.2X ", buff[i]);
+ }
+ printf("\n");
+ #endif
if (nread == 0)
{
diff --git a/mbus/mbus-serial.h b/mbus/mbus-serial.h
index 76445779..774dd62b 100755
--- a/mbus/mbus-serial.h
+++ b/mbus/mbus-serial.h
@@ -18,7 +18,12 @@
#ifndef MBUS_SERIAL_H
#define MBUS_SERIAL_H
+#ifdef _WIN32
+#include "../win/termiWin.h"
+#else
#include
+#endif
+
#include "mbus-protocol-aux.h"
#include "mbus-protocol.h"
@@ -45,4 +50,3 @@ void mbus_serial_data_free(mbus_handle *handle);
#endif
#endif /* MBUS_SERIAL_H */
-
diff --git a/mbus/mbus-tcp.c b/mbus/mbus-tcp.c
index 92919382..d4498ee2 100755
--- a/mbus/mbus-tcp.c
+++ b/mbus/mbus-tcp.c
@@ -8,25 +8,48 @@
//
//------------------------------------------------------------------------------
+#ifdef _WIN32
+#define __PRETTY_FUNCTION__ __FUNCSIG__
+#endif
+
+#ifdef _WIN32
+#include
+#include
+#include
+#include
+#include
+
+#include
+typedef SSIZE_T ssize_t;
+
+#ifndef SSIZE_MAX
+#ifdef _WIN64
+#define SSIZE_MAX _I64_MAX
+#else
+#define SSIZE_MAX LONG_MAX
+#endif
+#endif
+
+#else
#include
+#include
+#include
+#include
+#endif
+
#include
#include
-#include
#include
-#include
-#include
-#include
-
#include
#include
-#include
#include
#include "mbus-tcp.h"
#define PACKET_BUFF_SIZE 2048
+#define MAX_PORT_SIZE 6 // Size of port number + NULL char
static int tcp_timeout_sec = 4;
static int tcp_timeout_usec = 0;
@@ -38,11 +61,11 @@ int
mbus_tcp_connect(mbus_handle *handle)
{
char error_str[128], *host;
- struct hostent *host_addr;
- struct sockaddr_in s;
+ struct addrinfo hints, *servinfo, *p;
struct timeval time_out;
mbus_tcp_data *tcp_data;
- uint16_t port;
+ char port[MAX_PORT_SIZE];
+ int status;
if (handle == NULL)
return -1;
@@ -52,34 +75,60 @@ mbus_tcp_connect(mbus_handle *handle)
return -1;
host = tcp_data->host;
- port = tcp_data->port;
+ snprintf(port, MAX_PORT_SIZE, "%d", tcp_data->port);
+
+ #ifdef _WIN32
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
+ wVersionRequested = MAKEWORD(2, 2);
+
+ err = WSAStartup(wVersionRequested, &wsaData);
+ if (err != 0) {
+ /* Tell the user that we could not find a usable */
+ /* Winsock DLL. */
+ snprintf(error_str, sizeof(error_str), "%s: WSAStartup failed with error: %d", __PRETTY_FUNCTION__, err);
+ mbus_error_str_set(error_str);
+ return -1;
+ }
+ #endif
- //
- // create the TCP connection
- //
- if ((handle->fd = socket(AF_INET,SOCK_STREAM, 0)) < 0)
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ if ((status = getaddrinfo(host, port, &hints, &servinfo)) != 0)
{
- snprintf(error_str, sizeof(error_str), "%s: failed to setup a socket.", __PRETTY_FUNCTION__);
+ snprintf(error_str, sizeof(error_str), "%s: getaddrinfo: %s", __PRETTY_FUNCTION__, gai_strerror(status));
mbus_error_str_set(error_str);
return -1;
}
- s.sin_family = AF_INET;
- s.sin_port = htons(port);
-
- /* resolve hostname */
- if ((host_addr = gethostbyname(host)) == NULL)
+ // loop through all the results and connect to the first we can
+ for (p = servinfo; p != NULL; p = p->ai_next)
{
- snprintf(error_str, sizeof(error_str), "%s: unknown host: %s", __PRETTY_FUNCTION__, host);
- mbus_error_str_set(error_str);
- return -1;
+ if ((handle->fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
+ {
+ continue;
+ }
+
+ if (connect(handle->fd, p->ai_addr, p->ai_addrlen) == -1)
+ {
+ close(handle->fd);
+ continue;
+ }
+
+ break; // if we get here, we must have connected successfully
}
- memcpy((void *)(&s.sin_addr), (void *)(host_addr->h_addr), host_addr->h_length);
+ // Free addr info, we do not need it anymore
+ freeaddrinfo(servinfo);
- if (connect(handle->fd, (struct sockaddr *)&s, sizeof(s)) < 0)
+ if (p == NULL)
{
- snprintf(error_str, sizeof(error_str), "%s: Failed to establish connection to %s:%d", __PRETTY_FUNCTION__, host, port);
+ snprintf(error_str, sizeof(error_str), "%s: Failed to establish connection to %s:%s", __PRETTY_FUNCTION__, host, port);
mbus_error_str_set(error_str);
return -1;
}
@@ -87,9 +136,15 @@ mbus_tcp_connect(mbus_handle *handle)
// Set a timeout
time_out.tv_sec = tcp_timeout_sec; // seconds
time_out.tv_usec = tcp_timeout_usec; // microseconds
+
+ #ifdef _WIN32
+ uint64_t millis = (time_out.tv_sec * (uint64_t)1000) + (time_out.tv_usec / 1000);
+ setsockopt(handle->fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&millis, sizeof(time_out));
+ setsockopt(handle->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&millis, sizeof(time_out));
+ #else
setsockopt(handle->fd, SOL_SOCKET, SO_SNDTIMEO, &time_out, sizeof(time_out));
setsockopt(handle->fd, SOL_SOCKET, SO_RCVTIMEO, &time_out, sizeof(time_out));
-
+ #endif
return 0;
}
@@ -129,10 +184,15 @@ mbus_tcp_disconnect(mbus_handle *handle)
if (handle->fd < 0)
{
- return -1;
+ return -1;
}
+ #ifdef _WIN32
+ closesocket(handle->fd);
+ WSACleanup();
+ #else
close(handle->fd);
+ #endif
handle->fd = -1;
return 0;
@@ -160,7 +220,11 @@ mbus_tcp_send_frame(mbus_handle *handle, mbus_frame *frame)
return -1;
}
+ #ifdef _WIN32
+ if ((ret = send(handle->fd, buff, len, 0)) == len)
+ #else
if ((ret = write(handle->fd, buff, len)) == len)
+ #endif
{
//
// call the send event function, if the callback function is registered
@@ -208,13 +272,22 @@ int mbus_tcp_recv_frame(mbus_handle *handle, mbus_frame *frame)
return MBUS_RECV_RESULT_ERROR;
}
- nread = read(handle->fd, &buff[len], remaining);
+ #ifdef _WIN32
+ nread = recv(handle->fd, &buff[len], remaining, 0);
+ errno = WSAGetLastError();
+ #else
+ nread = read(handle->fd, &buff[len], remaining);
+ #endif
switch (nread) {
case -1:
if (errno == EINTR)
goto retry;
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK
+ #ifdef _WIN32
+ || errno == WSAETIMEDOUT
+ #endif
+ ) {
mbus_error_str_set("M-Bus tcp transport layer response timeout has been reached.");
return MBUS_RECV_RESULT_TIMEOUT;
}
diff --git a/mbus/mbus-tcp.h b/mbus/mbus-tcp.h
index 0d4e6b73..3916aa55 100755
--- a/mbus/mbus-tcp.h
+++ b/mbus/mbus-tcp.h
@@ -44,6 +44,3 @@ int mbus_tcp_set_timeout_set(double seconds);
#endif
#endif /* MBUS_TCP_H */
-
-
-
diff --git a/mbus/mbus.c b/mbus/mbus.c
index 0ff0f8ef..d5dca2e6 100644
--- a/mbus/mbus.c
+++ b/mbus/mbus.c
@@ -9,7 +9,16 @@
//------------------------------------------------------------------------------
#include "mbus-protocol.h"
+
+#ifdef _WIN32
+#define VERSION "0.9.0"
+#else
#include "../config.h"
+#endif
+
+#ifndef VERSION
+#define VERSION "0.9.0"
+#endif
//
//
diff --git a/mbus/mbus.h b/mbus/mbus.h
index 264c8e0b..310904a9 100644
--- a/mbus/mbus.h
+++ b/mbus/mbus.h
@@ -42,6 +42,11 @@
extern "C" {
#endif
+#ifdef _WIN32
+#define __PRETTY_FUNCTION__ __FUNCSIG__
+#define strdup _strdup
+#endif
+
//
//
//
diff --git a/test/test-frames/SLB_CF-Compact-Integral-MK-MaXX.xml b/test/test-frames/SLB_CF-Compact-Integral-MK-MaXX.xml
index c2492218..f120b186 100644
--- a/test/test-frames/SLB_CF-Compact-Integral-MK-MaXX.xml
+++ b/test/test-frames/SLB_CF-Compact-Integral-MK-MaXX.xml
@@ -58,7 +58,7 @@
Instantaneous value
0
Temperature Difference (1e-2 deg C)
- F00018
+ -18
diff --git a/test/test-frames/landis+gyr_ultraheat_t230.xml b/test/test-frames/landis+gyr_ultraheat_t230.xml
index ea3a8791..154261a4 100644
--- a/test/test-frames/landis+gyr_ultraheat_t230.xml
+++ b/test/test-frames/landis+gyr_ultraheat_t230.xml
@@ -72,7 +72,7 @@
Instantaneous value
0
Temperature Difference (1e-1 deg C)
- F00002
+ -2
diff --git a/win/termiWin.c b/win/termiWin.c
new file mode 100644
index 00000000..3db3367d
--- /dev/null
+++ b/win/termiWin.c
@@ -0,0 +1,548 @@
+/* termiWin.c
+*
+* Copyright (C) 2017 Christian Visintin - christian.visintin1997@gmail.com
+*
+* This file is part of "termiWin: a termios porting for Windows"
+*
+* termiWin is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* termiWin 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with termiWin. If not, see .
+*
+*/
+
+#include "termiWin.h"
+#include
+#include
+
+
+typedef struct COM
+{
+ HANDLE hComm;
+ int fd; //Actually it's completely useless
+ char* port;
+} COM;
+
+DCB SerialParams = { 0 }; //Initializing DCB structure
+struct COM com;
+COMMTIMEOUTS timeouts = { 0 }; //Initializing COMMTIMEOUTS structure
+
+//LOCAL functions
+
+/*nbyte 0->7*/
+int getByte(tcflag_t flag,int nbyte, int nibble) {
+
+ int byte;
+ if(nibble == 1) byte = (flag >> (8*(nbyte)) & 0x0f);
+ else byte = (flag >> (8*(nbyte)) & 0xf0);
+ return byte;
+
+}
+
+//INPUT FUNCTIONS
+
+int getIXOptions(tcflag_t flag) {
+
+ #define i_IXOFF 0x01
+ #define i_IXON 0x02
+ #define i_IXOFF_IXON 0x03
+ #define i_PARMRK 0x04
+ #define i_PARMRK_IXOFF 0x05
+ #define i_PARMRK_IXON 0x06
+ #define i_PARMRK_IXON_IXOFF 0x07
+
+ int byte = getByte(flag,1,1);
+
+ return byte;
+
+}
+
+//LOCALOPT FUNCTIONS
+
+int getEchoOptions(tcflag_t flag) {
+
+ #define l_NOECHO 0x00
+ #define l_ECHO 0x01
+ #define l_ECHO_ECHOE 0x03
+ #define l_ECHO_ECHOK 0x05
+ #define l_ECHO_ECHONL 0x09
+ #define l_ECHO_ECHOE_ECHOK 0x07
+ #define l_ECHO_ECHOE_ECHONL 0x0b
+ #define l_ECHO_ECHOE_ECHOK_ECHONL 0x0f
+ #define l_ECHO_ECHOK_ECHONL 0x0d
+ #define l_ECHOE 0x02
+ #define l_ECHOE_ECHOK 0x06
+ #define l_ECHOE_ECHONL 0x0a
+ #define l_ECHOE_ECHOK_ECHONL 0x0e
+ #define l_ECHOK 0x04
+ #define l_ECHOK_ECHONL 0x0c
+ #define l_ECHONL 0x08
+
+ int byte = getByte(flag,1,1);
+ return byte;
+
+}
+
+int getLocalOptions(tcflag_t flag) {
+
+ #define l_ICANON 0x10
+ #define l_ICANON_ISIG 0x50
+ #define l_ICANON_IEXTEN 0x30
+ #define l_ICANON_NOFLSH 0x90
+ #define l_ICANON_ISIG_IEXTEN 0x70
+ #define l_ICANON_ISIG_NOFLSH 0xd0
+ #define l_ICANON_IEXTEN_NOFLSH 0xb0
+ #define l_ICANON_ISIG_IEXTEN_NOFLSH 0xf0
+ #define l_ISIG 0x40
+ #define l_ISIG_IEXTEN 0x60
+ #define l_ISIG_NOFLSH 0xc0
+ #define l_ISIG_IEXTEN_NOFLSH 0xe0
+ #define l_IEXTEN 0x20
+ #define l_IEXTEN_NOFLSH 0xa0
+ #define l_NOFLSH 0x80
+
+ int byte = getByte(flag,1,0);
+ return byte;
+
+}
+
+int getToStop(tcflag_t flag) {
+
+ #define l_TOSTOP 0x01
+
+ int byte = getByte(flag,1,1);
+ return byte;
+
+}
+
+//CONTROLOPT FUNCTIONS
+
+int getCharSet(tcflag_t flag) {
+
+ //FLAG IS MADE UP OF 8 BYTES, A FLAG IS MADE UP OF A NIBBLE -> 4 BITS, WE NEED TO EXTRACT THE SECOND NIBBLE (1st) FROM THE FIFTH BYTE (6th).
+ int byte = getByte(flag,1,1);
+
+ switch(byte) {
+
+ case 0X0:
+ return CS5;
+ break;
+
+ case 0X4:
+ return CS6;
+ break;
+
+ case 0X8:
+ return CS7;
+ break;
+
+ case 0Xc:
+ return CS8;
+ break;
+
+ default:
+ return CS8;
+ break;
+
+ }
+
+}
+
+int getControlOptions(tcflag_t flag) {
+
+ #define c_ALL_ENABLED 0xd0
+ #define c_PAREVEN_CSTOPB 0x50
+ #define c_PAREVEN_NOCSTOPB 0x40
+ #define c_PARODD_NOCSTOPB 0xc0
+ #define c_NOPARENB_CSTOPB 0x10
+ #define c_ALL_DISABLED 0x00
+
+ int byte = getByte(flag,1,0);
+ return byte;
+
+}
+
+//LIBFUNCTIONS
+
+int tcgetattr(int fd, struct termios *termios_p) {
+
+ if(fd != com.fd) return -1;
+ int ret=0;
+
+ ret = GetCommState(com.hComm,&SerialParams);
+
+ return 0;
+
+}
+
+int tcsetattr(int fd, int optional_actions, const struct termios *termios_p) {
+
+ if(fd != com.fd) return -1;
+ int ret=0;
+
+ //Store flags into local variables
+ tcflag_t iflag = termios_p->c_iflag;
+ tcflag_t lflag = termios_p->c_lflag;
+ tcflag_t cflag = termios_p->c_cflag;
+ tcflag_t oflag = termios_p->c_oflag;
+
+ /*****************************************
+ iflag
+ *****************************************/
+
+ int IX = getIXOptions(iflag);
+
+ if( (IX == i_IXOFF_IXON) || (IX == i_PARMRK_IXON_IXOFF) ) {
+
+ SerialParams.fOutX = TRUE;
+ SerialParams.fInX = TRUE;
+ SerialParams.fTXContinueOnXoff = TRUE;
+
+ }
+
+ /*****************************************
+ lflag
+ *****************************************/
+
+ int EchoOpt = getEchoOptions(lflag);
+ int l_opt = getLocalOptions(lflag);
+ int tostop = getToStop(lflag);
+
+ //Missing parameters...
+
+ /*****************************************
+ cflag
+ *****************************************/
+
+ int CharSet = getCharSet(cflag);
+ int c_opt = getControlOptions(cflag);
+
+ switch(CharSet) {
+
+ case CS5:
+ SerialParams.ByteSize = 5;
+ break;
+
+ case CS6:
+ SerialParams.ByteSize = 6;
+ break;
+
+ case CS7:
+ SerialParams.ByteSize = 7;
+ break;
+
+ case CS8:
+ SerialParams.ByteSize = 8;
+ break;
+
+ }
+
+ switch(c_opt) {
+
+ case c_ALL_ENABLED:
+ SerialParams.Parity = ODDPARITY;
+ SerialParams.StopBits = TWOSTOPBITS;
+ break;
+
+ case c_ALL_DISABLED:
+ SerialParams.Parity = NOPARITY;
+ SerialParams.StopBits = ONESTOPBIT;
+ break;
+
+ case c_PAREVEN_CSTOPB:
+ SerialParams.Parity = EVENPARITY;
+ SerialParams.StopBits = TWOSTOPBITS;
+ break;
+
+ case c_PAREVEN_NOCSTOPB:
+ SerialParams.Parity = EVENPARITY;
+ SerialParams.StopBits = ONESTOPBIT;
+ break;
+
+ case c_PARODD_NOCSTOPB:
+ SerialParams.Parity = ODDPARITY;
+ SerialParams.StopBits = ONESTOPBIT;
+ break;
+
+ case c_NOPARENB_CSTOPB:
+ SerialParams.Parity = NOPARITY;
+ SerialParams.StopBits = TWOSTOPBITS;
+ break;
+
+ }
+
+ /*****************************************
+ oflag
+ *****************************************/
+
+ /*int OP;
+ if(oflag == OPOST)
+ else ...*/
+ //Missing parameters...
+
+ /*****************************************
+ special characters
+ *****************************************/
+
+ if(termios_p->c_cc[VEOF] != 0) SerialParams.EofChar = (char) termios_p->c_cc[VEOF];
+ if(termios_p->c_cc[VINTR] != 0) SerialParams.EvtChar = (char) termios_p->c_cc[VINTR];
+
+ if(termios_p->c_cc[VMIN] == 1) { //Blocking
+
+
+ timeouts.ReadIntervalTimeout = 0; // in milliseconds
+ timeouts.ReadTotalTimeoutConstant = 0; // in milliseconds
+ timeouts.ReadTotalTimeoutMultiplier = 0; // in milliseconds
+ timeouts.WriteTotalTimeoutConstant = 0; // in milliseconds
+ timeouts.WriteTotalTimeoutMultiplier = 0; // in milliseconds
+
+
+ }
+
+ else { //Non blocking
+
+ timeouts.ReadIntervalTimeout = termios_p->c_cc[VTIME]*100; // in milliseconds
+ timeouts.ReadTotalTimeoutConstant = termios_p->c_cc[VTIME]*100; // in milliseconds
+ timeouts.ReadTotalTimeoutMultiplier = termios_p->c_cc[VTIME]*100; // in milliseconds
+ timeouts.WriteTotalTimeoutConstant = termios_p->c_cc[VTIME]*100; // in milliseconds
+ timeouts.WriteTotalTimeoutMultiplier = termios_p->c_cc[VTIME]*100; // in milliseconds
+
+ }
+
+
+
+ SetCommTimeouts(com.hComm,&timeouts);
+
+ /*****************************************
+ EOF
+ *****************************************/
+
+ ret = SetCommState(com.hComm,&SerialParams);
+ if (ret != 0) return 0;
+ else return -1;
+
+}
+
+int tcsendbreak(int fd, int duration) {
+
+ if(fd != com.fd) return -1;
+
+ int ret = 0;
+ ret = TransmitCommChar(com.hComm,'\x00');
+ if(ret != 0) return 0;
+ else return -1;
+
+}
+
+int tcdrain(int fd) {
+
+ if(fd != com.fd) return -1;
+ return FlushFileBuffers(com.hComm);
+
+}
+
+int tcflush(int fd, int queue_selector) {
+
+ if(fd != com.fd) return -1;
+ int rc=0;
+
+ switch (queue_selector) {
+
+ case TCIFLUSH:
+ rc = PurgeComm(com.hComm, PURGE_RXCLEAR);
+ break;
+
+ case TCOFLUSH:
+ rc = PurgeComm(com.hComm, PURGE_TXCLEAR);
+ break;
+
+ case TCIOFLUSH:
+ rc = PurgeComm(com.hComm, PURGE_RXCLEAR);
+ rc *= PurgeComm(com.hComm, PURGE_TXCLEAR);
+ break;
+
+ default:
+ rc = 0;
+ break;
+
+ }
+
+ if(rc != 0) return 0;
+ else return -1;
+
+}
+
+int tcflow(int fd, int action) {
+
+ if(fd != com.fd) return -1;
+ int rc = 0;
+
+ switch (action) {
+
+ case TCOOFF:
+ rc = PurgeComm(com.hComm, PURGE_TXABORT);
+ break;
+
+ case TCOON:
+ rc = ClearCommBreak(com.hComm);
+ break;
+
+ case TCIOFF:
+ rc = PurgeComm(com.hComm, PURGE_RXABORT);
+ break;
+
+ case TCION:
+ rc = ClearCommBreak(com.hComm);
+ break;
+
+ default:
+ rc = 0;
+ break;
+
+ }
+
+ if(rc != 0) return 0;
+ else return -1;
+
+}
+
+void cfmakeraw(struct termios *termios_p) {
+
+ SerialParams.ByteSize = 8;
+ SerialParams.StopBits = ONESTOPBIT;
+ SerialParams.Parity = EVENPARITY;
+
+}
+
+speed_t cfgetispeed(const struct termios *termios_p) {
+
+ return SerialParams.BaudRate;
+
+}
+
+speed_t cfgetospeed(const struct termios *termios_p) {
+
+ return SerialParams.BaudRate;
+
+}
+
+int cfsetispeed(struct termios *termios_p, speed_t speed) {
+
+ SerialParams.BaudRate = speed;
+ return 0;
+
+}
+
+int cfsetospeed(struct termios *termios_p, speed_t speed) {
+
+ SerialParams.BaudRate = speed;
+ return 0;
+
+}
+
+int cfsetspeed(struct termios *termios_p, speed_t speed) {
+
+ SerialParams.BaudRate = speed;
+ return 0;
+
+}
+
+int selectSerial(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) {
+
+ SetCommMask(com.hComm, EV_RXCHAR);
+ DWORD dwEventMask;
+ WaitCommEvent(com.hComm, &dwEventMask, NULL);
+
+ if(dwEventMask == EV_RXCHAR) return com.fd;
+ else return -1;
+
+}
+
+int readFromSerial(int fd, char* buffer, int count) {
+
+ if(fd != com.fd) return -1;
+ int rc = 0;
+ int ret;
+
+ ret = ReadFile(com.hComm, buffer, count, &rc, NULL);
+
+ if (ret == 0) return -1;
+ else return rc;
+
+}
+
+int writeToSerial(int fd, char* buffer, int count) {
+
+ if(fd != com.fd) return -1;
+ int rc = 0;
+ int ret;
+
+ ret = WriteFile(com.hComm, buffer, count, &rc, NULL);
+
+ if (ret == 0) return -1;
+ else return rc;
+
+}
+
+int openSerial(char* portname, int opt) {
+
+
+ if (strlen(portname) < 4) return -1;
+
+ com.port = calloc(1,sizeof(char)*(strlen(portname)+1));
+ strncat(com.port, portname, strlen(portname));
+
+ switch (opt) {
+
+ case O_RDWR:
+ com.hComm = CreateFile(com.port, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+ break;
+
+ case O_RDONLY:
+ com.hComm = CreateFile(com.port, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
+ break;
+
+ case O_WRONLY:
+ com.hComm = CreateFile(com.port, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+ break;
+ }
+
+ if (com.hComm == INVALID_HANDLE_VALUE) return -1;
+ strncpy(portname, portname + 3, 1);
+ com.fd = atoi(portname); //COMx
+ SerialParams.DCBlength = sizeof(SerialParams);
+
+ if (!GetCommState(com.hComm, &SerialParams))
+ return -1;
+ return com.fd;
+
+}
+
+int closeSerial(int fd) {
+
+ int ret = CloseHandle(com.hComm);
+ if(ret != 0) return 0;
+ else return -1;
+
+}
+
+//Returns hComm from the COM structure
+HANDLE getHandle() {
+ return com.hComm;
+}
+
+int isatty(int fd) {
+
+ if(fd != com.fd) return -1;
+ if (GetFileType(com.hComm) != FILE_TYPE_CHAR ) return 0;
+ else return -1;
+
+}
diff --git a/win/termiWin.h b/win/termiWin.h
new file mode 100644
index 00000000..e8b3be5d
--- /dev/null
+++ b/win/termiWin.h
@@ -0,0 +1,193 @@
+/* termiWin.h
+*
+* Copyright (C) 2017 Christian Visintin - christian.visintin1997@gmail.com
+*
+* This file is part of "termiWin: a termios porting for Windows"
+*
+* termiWin is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* termiWin 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with termiWin. If not, see .
+*
+*/
+
+#ifndef TERMIWIN_H_
+#define TERMIWIN_H_
+#endif
+
+#ifdef _WIN64
+#define WIN64_LEAN_AND_MEAN
+#endif
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include
+#include
+#pragma comment(lib, "Ws2_32.lib")
+
+/*Redefining functions from winsock to termiWin. This is very important since winsock2 defines functions such as close as closesocket we have to redefine it*/
+
+/*
+#define read readFromSerial
+#define write writeToSerial
+#define select selectSerial
+#define open openSerial
+#define close closeSerial
+*/
+//Serial options - Linux -> Windows
+
+/*setAttr flags - ~ in front of flags -> deny them*/
+
+//iFlag
+
+#define INPCK 0x00004000 /*If this bit is set, input parity checking is enabled. If it is not set, no checking at all is done for parity errors on input; the characters are simply passed through to the application.*/
+#define IGNPAR 0x00001000 /*If this bit is set, any byte with a framing or parity error is ignored. This is only useful if INPCK is also set.*/
+#define PARMRK 0x00040000 /*If this bit is set, input bytes with parity or framing errors are marked when passed to the program. This bit is meaningful only when INPCK is set and IGNPAR is not set.*/
+#define ISTRIP 0x00008000 /*If this bit is set, valid input bytes are stripped to seven bits; otherwise, all eight bits are available for programs to read. */
+#define IGNBRK 0x00000400 /*If this bit is set, break conditions are ignored. */
+#define BRKINT 0x00000100 /*If this bit is set and IGNBRK is not set, a break condition clears the terminal input and output queues and raises a SIGINT signal for the foreground process group associated with the terminal. */
+#define IGNCR 0x00000800 /*If this bit is set, carriage return characters ('\r') are discarded on input. Discarding carriage return may be useful on terminals that send both carriage return and linefeed when you type the RET key. */
+#define ICRNL 0x00000200 /*If this bit is set and IGNCR is not set, carriage return characters ('\r') received as input are passed to the application as newline characters ('\n').*/
+#define INLCR 0x00002000 /*If this bit is set, newline characters ('\n') received as input are passed to the application as carriage return characters ('\r').*/
+#define IXOFF 0x00010000 /*If this bit is set, start/stop control on input is enabled. In other words, the computer sends STOP and START characters as necessary to prevent input from coming in faster than programs are reading it. The idea is that the actual terminal hardware that is generating the input data responds to a STOP character by suspending transmission, and to a START character by resuming transmission.*/
+#define IXON 0x00020000 /*If this bit is set, start/stop control on output is enabled. In other words, if the computer receives a STOP character, it suspends output until a START character is received. In this case, the STOP and START characters are never passed to the application program. If this bit is not set, then START and STOP can be read as ordinary characters.*/
+
+//lFlag
+
+#define ICANON 0x00001000 /*This bit, if set, enables canonical input processing mode. Otherwise, input is processed in noncanonical mode. */
+#define ECHO 0x00000100 /*If this bit is set, echoing of input characters back to the terminal is enabled.*/
+#define ECHOE 0x00000200 /*If this bit is set, echoing indicates erasure of input with the ERASE character by erasing the last character in the current line from the screen. Otherwise, the character erased is re-echoed to show what has happened (suitable for a printing terminal). */
+#define ECHOK 0x00000400 /*This bit enables special display of the KILL character by moving to a new line after echoing the KILL character normally. The behavior of ECHOKE (below) is nicer to look at.*/
+#define ECHONL 0x00000800 /*If this bit is set and the ICANON bit is also set, then the newline ('\n') character is echoed even if the ECHO bit is not set. */
+#define ISIG 0x00004000 /*This bit controls whether the INTR, QUIT, and SUSP characters are recognized. The functions associated with these characters are performed if and only if this bit is set. Being in canonical or noncanonical input mode has no effect on the interpretation of these characters. */
+#define IEXTEN 0x00002000 /*On BSD systems and GNU/Linux and GNU/Hurd systems, it enables the LNEXT and DISCARD characters.*/
+#define NOFLSH 0x00008000 /*Normally, the INTR, QUIT, and SUSP characters cause input and output queues for the terminal to be cleared. If this bit is set, the queues are not cleared. */
+#define TOSTOP 0x00010000 /*If this bit is set and the system supports job control, then SIGTTOU signals are generated by background processes that attempt to write to the terminal.*/
+
+//cFlag
+
+#define CSTOPB 0x00001000 /*If this bit is set, two stop bits are used. Otherwise, only one stop bit is used. */
+#define PARENB 0x00004000 /*If this bit is set, generation and detection of a parity bit are enabled*/
+#define PARODD 0x00008000 /*This bit is only useful if PARENB is set. If PARODD is set, odd parity is used, otherwise even parity is used. */
+#define CSIZE 0x00000c00 /*This is a mask for the number of bits per character. */
+#define CS5 0x00000000 /*This specifies five bits per byte. */
+#define CS6 0x00000400 /*This specifies six bits per byte. */
+#define CS7 0x00000800 /*This specifies seven bits per byte. */
+#define CS8 0x00000c00 /*This specifies eight bits per byte. */
+
+#define CLOCAL 0x00000000 // No idea if this makes sense
+#define CREAD 0x00000000 // No idea if this makes sense
+//oFlag
+
+#define OPOST 0x00000100 /*If this bit is set, output data is processed in some unspecified way so that it is displayed appropriately on the terminal device. This typically includes mapping newline characters ('\n') onto carriage return and linefeed pairs. */
+
+//cc
+
+#define VEOF 0
+#define VEOL 1
+#define VERASE 2
+#define VINTR 3
+#define VKILL 4
+#define VMIN 5 /*If set to 0, serial communication is NOT-BLOCKING, otherwise is BLOCKING*/
+#define VQUIT 6
+#define VSTART 7
+#define VSTOP 8
+#define VSUSP 9
+#define VTIME 10
+
+//END OF setAttr flags
+
+/*Controls*/
+#define TIOMBIC DTR_CONTROL_DISABLE
+#define TIOMBIS DTR_CONTROL_ENABLE
+#define CRTSCTS RTS_CONTROL_ENABLE
+
+/*Others*/
+#define NCCS 11
+
+//Baud speed
+#define B300 CBR_300
+#define B600 CBR_600
+#define B1200 CBR_1200
+#define B2400 CBR_2400
+#define B4800 CBR_4800
+#define B9600 CBR_9600
+#define B19200 CBR_19200
+#define B38400 CBR_38400
+#define B57600 CBR_57600
+#define B115200 CBR_115200
+
+/*Attributes optional_actions*/
+#define TCSANOW 0
+#define TCSADRAIN 1
+#define TCSAFLUSH 2
+
+/*TCFLUSH options*/
+#define TCIFLUSH 0
+#define TCOFLUSH 1
+#define TCIOFLUSH 2
+
+/*TCFLOW optons*/
+
+#define TCOOFF 0
+#define TCOON 1
+#define TCIOFF 2
+#define TCION 3
+
+//typdef
+typedef unsigned tcflag_t; /*This is an unsigned integer type used to represent the various bit masks for terminal flags.*/
+typedef unsigned cc_t; /*This is an unsigned integer type used to represent characters associated with various terminal control functions.*/
+typedef unsigned speed_t; /*used for terminal baud rates*/
+
+typedef struct termios
+{
+
+ tcflag_t c_iflag; /*input modes*/
+ tcflag_t c_oflag; /*output modes*/
+ tcflag_t c_cflag; /*control modes*/
+ tcflag_t c_lflag; /*local modes*/
+ cc_t c_cc[NCCS]; /*special character*/
+
+} termios;
+
+//Serial configuration functions
+
+int tcgetattr(int fd, struct termios *termios_p);
+int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);
+int tcsendbreak(int fd, int duration);
+int tcdrain(int fd);
+int tcflush(int fd, int queue_selector);
+int tcflow(int fd, int action);
+void cfmakeraw(struct termios *termios_p);
+speed_t cfgetispeed(const struct termios *termios_p);
+speed_t cfgetospeed(const struct termios *termios_p);
+int cfsetispeed(struct termios *termios_p, speed_t speed);
+int cfsetospeed(struct termios *termios_p, speed_t speed);
+int cfsetspeed(struct termios * termios_p, speed_t speed);
+
+//Write/Read/Open/Close/Select Functions
+
+int selectSerial(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
+int readFromSerial(int fd, char* buffer, int count);
+int writeToSerial(int fd, char* buffer, int count);
+int openSerial(char* portname, int opt);
+int closeSerial(int fd);
+
+//get Handle out of the COM structure
+HANDLE getHandle();
+
+int isatty(int fd);
+
+#endif
+
+#ifndef _WIN32
+#pragma message("-Warning: termiWin requires a Windows system!")
+#endif