diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..39d8667
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,4 @@
+* text=auto eol=lf
+*.sln text eol=crlf
+*.vcxproj text eol=crlf
+*.vcxproj.filters text eol=crlf
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..ce7a95a
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,264 @@
+#
+# build.yml - GitHub build action for libserialport adapted from AVRDUDE
+# Copyright (C) 2021 Marius Greuel
+# Copyright (C) 2024 Hans Ulrich Niedermann
+#
+# This program 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 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 this program. If not, see .
+#
+
+name: Build
+
+on:
+ push:
+ branches-ignore:
+ - 'onlinedocs'
+ pull_request:
+ branches-ignore:
+ - 'onlinedocs'
+ workflow_call:
+
+env:
+ BUILD_TYPE: RelWithDebInfo
+
+jobs:
+
+ linux-x86_64:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install prerequisites
+ run: >-
+ sudo apt-get update
+
+ sudo apt-get install -y
+ build-essential
+ cmake
+ automake
+ libtool
+ - name: "at: autoreconf"
+ run: >-
+ ./autogen.sh
+ - name: "at: configure"
+ run: >-
+ mkdir _build-at && cd _build-at
+
+ ../configure
+ --prefix=/usr/local
+ - name: "at: build"
+ run: make -C _build-at -j$(nproc)
+ - name: "at: install"
+ run: make -C _build-at install DESTDIR=$PWD/_dest-at
+ - name: "at: list installed files"
+ run: find _dest-at | env LC_ALL=C sort | sed 's|^_dest-at||'
+ - name: "at: distcheck"
+ run: make -C _build-at -j$(nproc) distcheck
+ - name: "cm: configure"
+ run: >-
+ cmake
+ -B _build-cm
+ -D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
+ -D CMAKE_INSTALL_PREFIX:PATH=/usr/local
+ - name: "cm: build"
+ run: cmake --build _build-cm
+ - name: "cm: install"
+ run: cmake --build _build-cm --target install DESTDIR=$PWD/_dest-cm
+ - name: "cm: list installed files"
+ run: find _dest-cm | env LC_ALL=C sort | sed 's|^_dest-cm||'
+
+ linux:
+ runs-on: ubuntu-latest
+ container: debian:11
+ strategy:
+ matrix:
+ include:
+ - { arch: i386, processor: i686, prefix: i686-linux-gnu, inc-lib: i386-linux-gnu }
+ - { arch: armhf, processor: armhf, prefix: arm-linux-gnueabihf, inc-lib: arm-linux-gnueabihf }
+ - { arch: arm64, processor: aarch64, prefix: aarch64-linux-gnu, inc-lib: aarch64-linux-gnu }
+ steps:
+ - uses: actions/checkout@v4
+ - name: Add architecture
+ run: |
+ dpkg --add-architecture ${{matrix.arch}}
+ apt-get update
+ - name: Install prerequisites
+ run: >-
+ apt-get update
+
+ apt-get install -y
+ git
+ cmake
+ automake
+ libtool
+ crossbuild-essential-${{matrix.arch}}
+ - name: "cm: configure"
+ run: >-
+ cmake
+ -D DEBUG_CMAKE=1
+ -D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
+ -D CMAKE_SYSTEM_NAME=Linux
+ -D CMAKE_SYSTEM_PROCESSOR=${{matrix.processor}}
+ -D CMAKE_C_COMPILER=${{matrix.prefix}}-gcc
+ -D CMAKE_FIND_ROOT_PATH=/usr/${{matrix.prefix}}
+ -D CMAKE_INCLUDE_PATH=/usr/include/${{matrix.inc-lib}}
+ -D CMAKE_LIBRARY_PATH=/usr/lib/${{matrix.inc-lib}}
+ -B _build-cm
+ - name: "cm: build"
+ run: cmake --build _build-cm
+ - name: "cm: install"
+ run: cmake --build _build-cm --target install DESTDIR=$PWD/_dest-cm
+ - name: "cm: list installed files"
+ run: find _dest-cm | env LC_ALL=C sort | sed 's|^_dest-cm||'
+ - name: "at: autoreconf"
+ run: >-
+ ./autogen.sh
+ - name: "at: configure"
+ run: >-
+ mkdir _build-at && cd _build-at
+
+ ../configure
+ --prefix=/usr/local
+ - name: "at: build"
+ run: make -C _build-at -j$(nproc)
+ - name: "at: install"
+ run: make -C _build-at install DESTDIR=$PWD/_dest-at
+ - name: "at: list installed files"
+ run: find _dest-at | env LC_ALL=C sort | sed 's|^_dest-at||'
+
+ macos-x86_64:
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install prerequisites
+ run: >-
+ # brew update
+
+ brew install
+ cmake
+ automake
+ autoconf
+ libtool
+ - name: "cm: configure"
+ run: >-
+ cmake
+ -D CMAKE_C_FLAGS=-I/usr/local/include
+ -D CMAKE_EXE_LINKER_FLAGS=-L/usr/local/Cellar
+ -D DEBUG_CMAKE=1
+ -D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
+ -B _build-cm
+ - name: "cm: build"
+ run: cmake --build _build-cm --verbose
+ - name: "cm: install"
+ run: cmake --build _build-cm --target install DESTDIR=$PWD/_dest-cm
+ - name: "cm: list installed files"
+ run: find _dest-cm | env LC_ALL=C sort | sed 's|^_dest-cm||'
+ - name: "at: autoreconf"
+ run: >-
+ ./autogen.sh
+ - name: "at: configure"
+ run: >-
+ mkdir _build-at && cd _build-at
+
+ ../configure
+ --prefix=/usr/local
+ - name: "at: build"
+ run: make -C _build-at -j$(nproc)
+ - name: "at: install"
+ run: make -C _build-at install DESTDIR=$PWD/_dest-at
+ - name: "at: list installed files"
+ run: find _dest-at | env LC_ALL=C sort | sed 's|^_dest-at||'
+
+ msvc:
+ runs-on: windows-latest
+ strategy:
+ matrix:
+ include:
+ - { arch: x86, platform: Win32 }
+ - { arch: x64, platform: x64 }
+ - { arch: arm64, platform: ARM64 }
+ steps:
+ - uses: actions/checkout@v4
+ - name: "cm: configure"
+ run: >-
+ cmake
+ -A ${{matrix.platform}}
+ -D DEBUG_CMAKE=1
+ -D CMAKE_SYSTEM_VERSION=11
+ -D CMAKE_C_FLAGS_RELWITHDEBINFO="/MT /GL /Zi /O2 /Ob1 /DNDEBUG"
+ -D CMAKE_CXX_FLAGS_RELWITHDEBINFO="/MT /GL /Zi /O2 /Ob1 /DNDEBUG"
+ -D CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO="/DEBUG /INCREMENTAL:NO /LTCG /OPT:REF /OPT:ICF"
+ -B _build-cm
+ - name: "cm: build"
+ run: cmake --build _build-cm --config ${{env.BUILD_TYPE}} --verbose
+ - name: "cm: install"
+ run: cmake --build _build-cm --target install
+
+ # This is running in powershell, not sh. Therefore find, env,
+ # sort do not work as usual.
+
+ mingw:
+ runs-on: windows-latest
+ defaults:
+ run:
+ shell: msys2 {0}
+ strategy:
+ matrix:
+ include:
+ - { sys: mingw64, env: x86_64 }
+ - { sys: ucrt64, env: ucrt-x86_64 }
+ - { sys: clang64, env: clang-x86_64 }
+ steps:
+ - uses: actions/checkout@v4
+ - uses: msys2/setup-msys2@v2
+ with:
+ msystem: ${{matrix.sys}}
+ update: true
+ install: >-
+ base-devel
+ mingw-w64-${{matrix.env}}-gcc
+ mingw-w64-${{matrix.env}}-cmake
+ automake1.16
+ autoconf2.72
+ mingw-w64-${{matrix.env}}-libtool
+ - name: "cm: configure"
+ run: >-
+ cmake
+ -G"MSYS Makefiles"
+ -D DEBUG_CMAKE=1
+ -D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
+ -B _build-cm
+ - name: "cm: build"
+ run: cmake --build _build-cm --verbose
+ - name: "cm: install"
+ run: cmake --build _build-cm --target install DESTDIR=$PWD/_dest-cm
+ - name: "cm: list installed files"
+ run: find _dest-cm | env LC_ALL=C sort | sed 's|^_dest-cm||'
+ - name: "at: autoreconf"
+ run: >-
+ ACV=-2.72
+
+ AMV=-1.16
+
+ env ACLOCAL=aclocal$AMV AUTOMAKE=automake$AMV AUTORECONF=autoreconf$ACV AUTOCONF=autoconf$ACV AUTOM4TE=autom4te$ACV AUTOHEADER=autoheader$ACV ./autogen.sh
+ - name: "at: configure"
+ run: >-
+ mkdir _build-at && cd _build-at
+
+ ../configure
+ --prefix=/usr/local
+ - name: "at: build"
+ run: make -C _build-at -j$(nproc)
+ - name: "at: install"
+ run: make -C _build-at install DESTDIR=$PWD/_dest-at
+ - name: "at: list installed files"
+ run: find _dest-at | env LC_ALL=C sort | sed 's|^_dest-at||'
diff --git a/.gitignore b/.gitignore
index 353d778..6f73534 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,12 @@ Debug/
Release/
x64/
*.vcxproj.user
+
+/_amb/
+/_amb-*/
+/_amd/
+/_amd-*/
+/_cmb/
+/_cmb-*/
+/_cmd/
+/_cmd-*/
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..a948ec1
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,143 @@
+# ======================================================================
+# CMakeLists.txt. Generated from CMakeLists.txt.in by configure.ac.
+# ======================================================================
+# !!!!!!! DO NOT MODIFY THIS FILE !!!!!!!!
+# ======================================================================
+# EDIT CMakeLists.txt.in INSTEAD AND RE-RUN autoreconf/autogen.sh
+# ======================================================================
+
+cmake_minimum_required(VERSION 3.14)
+
+project(libserialport
+ VERSION "0.1.1.23"
+ DESCRIPTION "avrdudes bugfix fork of sigrok libserialport"
+ HOMEPAGE_URL "https://github.com/avrdudes/libserialport"
+ LANGUAGES C
+)
+
+include(GNUInstallDirs)
+
+configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/libserialport.pc.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/libserialport.pc"
+)
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libserialport.pc"
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
+)
+
+if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ set(LSP_SOURCES "macosx.c")
+elseif (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
+ set(LSP_SOURCES "freebsd.c")
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ set(LSP_SOURCES linux.c linux_termios.c linux_termios.h)
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ set(LSP_SOURCES "windows.c")
+else()
+ message(FATAL_ERROR
+ config.h
+ "${CMAKE_PROJECT_NAME} does not support this system: ${CMAKE_SYSTEM_NAME}")
+endif()
+
+set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
+try_compile(VISIBILITY_CONTROL_ATTRIBUTE
+ "${PROJECT_BINARY_DIR}/bindir1"
+ "${CMAKE_CURRENT_SOURCE_DIR}/test-visibility-control-attribute.c"
+)
+try_compile(VISIBILITY_CONTROL_DECLSPEC
+ "${PROJECT_BINARY_DIR}/bindir2"
+ "${CMAKE_CURRENT_SOURCE_DIR}/test-visibility-control-declspec.c"
+)
+if(VISIBILITY_CONTROL_ATTRIBUTE)
+ set(SP_API "__attribute__((visibility(\"default\")))")
+ set(SP_PRIV "__attribute__((visibility(\"hidden\")))")
+elseif(VISIBILITY_CONTROL_DECLSPEC)
+ set(SP_API "__declspec(dllexport)")
+ set(SP_PRIV "")
+else()
+ set(SP_API "")
+ set(SP_PRIV "")
+endif()
+
+set(EXTRA_WINDOWS_SOURCES)
+set(EXTRA_WINDOWS_INCLUDES)
+set(EXTRA_WINDOWS_RESOURCES)
+set(EXTRA_WINDOWS_LIBRARIES)
+
+if(WIN32 OR MINGW)
+ configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/windows.rc.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/windows.rc"
+ )
+ list(APPEND EXTRA_WINDOWS_RESOURCES "${CMAKE_CURRENT_BINARY_DIR}/windows.rc")
+ list(APPEND EXTRA_WINDOWS_LIBRARIES setupapi ws2_32)
+endif()
+
+if(MSVC)
+else()
+ add_compile_options(-Wall -Wextra -Wno-unused-parameter) # -Werror)
+endif()
+
+# FIXME: -no-undefined for Linux
+
+configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake-config.h.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/config.h"
+)
+
+add_library(libserialport SHARED
+ serialport.c
+ timing.c
+ ${LSP_SOURCES}
+ "${CMAKE_CURRENT_BINARY_DIR}/config.h"
+ ${EXTRA_WINDOWS_SOURCES}
+ ${EXTRA_WINDOWS_RESOURCES}
+)
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ set(EXTRA_MACOS_LIBRARIES
+ "-framework IOKit"
+ "-framework CoreFoundation"
+ )
+else()
+ set(EXTRA_MACOS_LIBRARIES)
+endif()
+
+target_compile_features(libserialport PRIVATE c_std_99)
+target_link_libraries(libserialport
+ PUBLIC
+ ${EXTRA_WINDOWS_LIBRARIES}
+ ${EXTRA_MACOS_LIBRARIES}
+)
+set_target_properties(libserialport PROPERTIES C_EXTENSIONS OFF)
+
+if(MSVC OR MINGW)
+ target_compile_definitions(libserialport
+ PRIVATE LIBSERIALPORT_MSBUILD
+ )
+else()
+ target_compile_definitions(libserialport
+ PRIVATE LIBSERIALPORT_ATBUILD
+ )
+endif()
+
+target_include_directories(libserialport
+ PUBLIC
+ "${PROJECT_BINARY_DIR}"
+ "${PROJECT_SOURCE_DIR}"
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+)
+
+set_target_properties(libserialport PROPERTIES
+ PREFIX ""
+ PUBLIC_HEADER "libserialport.h"
+ VERSION 0.1.0
+ SOVERSION 0
+)
+
+install(TARGETS libserialport
+ LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ PUBLIC_HEADER DESTINATION include COMPONENT dev
+)
diff --git a/CMakeLists.txt.in b/CMakeLists.txt.in
new file mode 100644
index 0000000..9bcb925
--- /dev/null
+++ b/CMakeLists.txt.in
@@ -0,0 +1,137 @@
+# @configure_input@
+
+cmake_minimum_required(VERSION 3.14)
+
+project(@PACKAGE_TARNAME@
+ VERSION "@PACKAGE_VERSION@"
+ DESCRIPTION "@PACKAGE_NAME@"
+ HOMEPAGE_URL "@PACKAGE_URL@"
+ LANGUAGES C
+)
+
+include(GNUInstallDirs)
+
+configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/libserialport.pc.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/libserialport.pc"
+)
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libserialport.pc"
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
+)
+
+if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ set(LSP_SOURCES "macosx.c")
+elseif (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
+ set(LSP_SOURCES "freebsd.c")
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ set(LSP_SOURCES linux.c linux_termios.c linux_termios.h)
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ set(LSP_SOURCES "windows.c")
+else()
+ message(FATAL_ERROR
+ config.h
+ "${CMAKE_PROJECT_NAME} does not support this system: ${CMAKE_SYSTEM_NAME}")
+endif()
+
+set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
+try_compile(VISIBILITY_CONTROL_ATTRIBUTE
+ "${PROJECT_BINARY_DIR}/bindir1"
+ "${CMAKE_CURRENT_SOURCE_DIR}/test-visibility-control-attribute.c"
+)
+try_compile(VISIBILITY_CONTROL_DECLSPEC
+ "${PROJECT_BINARY_DIR}/bindir2"
+ "${CMAKE_CURRENT_SOURCE_DIR}/test-visibility-control-declspec.c"
+)
+if(VISIBILITY_CONTROL_ATTRIBUTE)
+ set(SP_API "__attribute__((visibility(\"default\")))")
+ set(SP_PRIV "__attribute__((visibility(\"hidden\")))")
+elseif(VISIBILITY_CONTROL_DECLSPEC)
+ set(SP_API "__declspec(dllexport)")
+ set(SP_PRIV "")
+else()
+ set(SP_API "")
+ set(SP_PRIV "")
+endif()
+
+set(EXTRA_WINDOWS_SOURCES)
+set(EXTRA_WINDOWS_INCLUDES)
+set(EXTRA_WINDOWS_RESOURCES)
+set(EXTRA_WINDOWS_LIBRARIES)
+
+if(WIN32 OR MINGW)
+ configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/windows.rc.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/windows.rc"
+ )
+ list(APPEND EXTRA_WINDOWS_RESOURCES "${CMAKE_CURRENT_BINARY_DIR}/windows.rc")
+ list(APPEND EXTRA_WINDOWS_LIBRARIES setupapi ws2_32)
+endif()
+
+if(MSVC)
+else()
+ add_compile_options(-Wall -Wextra -Wno-unused-parameter) # -Werror)
+endif()
+
+# FIXME: -no-undefined for Linux
+
+configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake-config.h.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/config.h"
+)
+
+add_library(libserialport SHARED
+ serialport.c
+ timing.c
+ ${LSP_SOURCES}
+ "${CMAKE_CURRENT_BINARY_DIR}/config.h"
+ ${EXTRA_WINDOWS_SOURCES}
+ ${EXTRA_WINDOWS_RESOURCES}
+)
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ set(EXTRA_MACOS_LIBRARIES
+ "-framework IOKit"
+ "-framework CoreFoundation"
+ )
+else()
+ set(EXTRA_MACOS_LIBRARIES)
+endif()
+
+target_compile_features(libserialport PRIVATE c_std_99)
+target_link_libraries(libserialport
+ PUBLIC
+ ${EXTRA_WINDOWS_LIBRARIES}
+ ${EXTRA_MACOS_LIBRARIES}
+)
+set_target_properties(libserialport PROPERTIES C_EXTENSIONS OFF)
+
+if(MSVC OR MINGW)
+ target_compile_definitions(libserialport
+ PRIVATE LIBSERIALPORT_MSBUILD
+ )
+else()
+ target_compile_definitions(libserialport
+ PRIVATE LIBSERIALPORT_ATBUILD
+ )
+endif()
+
+target_include_directories(libserialport
+ PUBLIC
+ "${PROJECT_BINARY_DIR}"
+ "${PROJECT_SOURCE_DIR}"
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+)
+
+set_target_properties(libserialport PROPERTIES
+ PREFIX ""
+ PUBLIC_HEADER "libserialport.h"
+ VERSION @CMAKE_LIB_VERSION@
+ SOVERSION @CMAKE_LIB_SOVERSION@
+)
+
+install(TARGETS libserialport
+ LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ PUBLIC_HEADER DESTINATION include COMPONENT dev
+)
diff --git a/Doxyfile b/Doxyfile.in
similarity index 99%
rename from Doxyfile
rename to Doxyfile.in
index 0ac1014..58349ee 100644
--- a/Doxyfile
+++ b/Doxyfile.in
@@ -819,7 +819,7 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
-INPUT = libserialport.h
+INPUT = @abs_srcdir@/libserialport.h
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/Makefile.am b/Makefile.am
index 9b017eb..84ceada 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -28,6 +28,8 @@ AM_CFLAGS = -std=c99 -Wall -Wextra -pedantic -Wmissing-prototypes -Wshadow
# using autotools.
AM_CFLAGS += -DLIBSERIALPORT_ATBUILD
+noinst_DATA =
+
lib_LTLIBRARIES = libserialport.la
libserialport_la_SOURCES = serialport.c timing.c libserialport_internal.h
@@ -51,7 +53,7 @@ if MACOSX
libserialport_la_LDFLAGS += -framework IOKit -framework CoreFoundation
endif
-nodist_include_HEADERS = libserialport.h
+include_HEADERS = libserialport.h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libserialport.pc
@@ -70,14 +72,73 @@ EXTRA_DIST = Doxyfile \
examples/await_events.c \
examples/handle_errors.c
-MAINTAINERCLEANFILES = ChangeLog
+EXTRA_DIST += AUTHORS
+EXTRA_DIST += COPYING
+EXTRA_DIST += NEWS
+EXTRA_DIST += README
+
+EXTRA_DIST += autogen.sh
+EXTRA_DIST += config-header.py
+EXTRA_DIST += config-pattern
+
+EXTRA_DIST += common.props
+EXTRA_DIST += debug.props
+EXTRA_DIST += release.props
+
+EXTRA_DIST += libserialport.sln
+EXTRA_DIST += libserialport.vcxproj
+EXTRA_DIST += libserialport.vcxproj.filters
+
+EXTRA_DIST += examples/Makefile
+EXTRA_DIST += examples/README
+EXTRA_DIST += examples/examples.sln
+
+EXTRA_DIST += examples/await_events.c
+EXTRA_DIST += examples/projects/await_events.vcxproj
+EXTRA_DIST += examples/projects/await_events.vcxproj.filters
+
+EXTRA_DIST += examples/handle_errors.c
+EXTRA_DIST += examples/projects/handle_errors.vcxproj
+EXTRA_DIST += examples/projects/handle_errors.vcxproj.filters
+
+EXTRA_DIST += examples/list_ports.c
+EXTRA_DIST += examples/projects/list_ports.vcxproj
+EXTRA_DIST += examples/projects/list_ports.vcxproj.filters
+
+EXTRA_DIST += examples/port_config.c
+EXTRA_DIST += examples/projects/port_config.vcxproj
+EXTRA_DIST += examples/projects/port_config.vcxproj.filters
+
+EXTRA_DIST += examples/port_info.c
+EXTRA_DIST += examples/projects/port_info.vcxproj
+EXTRA_DIST += examples/projects/port_info.vcxproj.filters
+
+EXTRA_DIST += examples/send_receive.c
+EXTRA_DIST += examples/projects/send_receive.vcxproj
+EXTRA_DIST += examples/projects/send_receive.vcxproj.filters
+
+EXTRA_DIST += CMakeLists.txt.in
+EXTRA_DIST += $(srcdir)/CMakeLists.txt
.PHONY: ChangeLog doc
ChangeLog:
- git --git-dir '$(top_srcdir)/.git' log >$@ || touch $@
+if HAVE_PROG_GIT
+ if test -d '$(top_srcdir)/.git'; then \
+ $(GIT) --git-dir '$(top_srcdir)/.git' log > ChangeLog; \
+ else \
+ echo "Generated dummy ChangeLog file (no .git directory)" > ChangeLog; \
+ fi
+else
+ echo "Generated dummy ChangeLog file (no git tool)" > ChangeLog
+endif
+DISTCLEANFILES = ChangeLog
dist-hook: ChangeLog
-doc: $(nodist_include_HEADERS) $(top_srcdir)/Doxyfile
- doxygen $(top_srcdir)/Doxyfile
+if HAVE_PROG_DOXYGEN
+doc: $(srcdir)/libserialport.h Doxyfile
+ doxygen `test -f Doxyfile || echo '$(srcdir)/'`Doxyfile
+endif
+
+EXTRA_DIST += windows.rc.in
diff --git a/NEWS b/NEWS
index 7afa688..3ed1fd8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,8 @@
+0.1.1.23 (2024-02-20)
+---------------------
+
+ * Fix some devices on OSX (make buffer large enough for OSX class string)
+
0.1.1 (2016-01-27)
------------------
diff --git a/README b/README
index 817dff7..9f0b05d 100644
--- a/README
+++ b/README
@@ -2,6 +2,12 @@
libserialport: cross-platform library for accessing serial ports
-------------------------------------------------------------------------------
+ /---------------------------------\
+ | THIS IS A FORK OF libserialport |
+ | FOR THE avrdude PROJECT TO HELP |
+ | COLLECT FIXES TO FEED UPSTREAM. |
+ \---------------------------------/
+
libserialport is a minimal library written in C that is intended to take care
of the OS-specific details when writing software that uses serial ports.
diff --git a/autogen.sh b/autogen.sh
index 5e10887..5073921 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -23,4 +23,4 @@ test -n "$srcdir" || srcdir=`dirname "$0"`
test -n "$srcdir" || srcdir=.
test -d "$srcdir/autostuff" || mkdir "$srcdir/autostuff"
-autoreconf --force --install --verbose "$srcdir"
+${AUTORECONF-autoreconf} --force --install --verbose "$srcdir"
diff --git a/buildstuff/sed-substitute b/buildstuff/sed-substitute
new file mode 100755
index 0000000..e17bab5
--- /dev/null
+++ b/buildstuff/sed-substitute
@@ -0,0 +1,94 @@
+#! /bin/sh
+#
+# Usage:
+# sed-substitute sed-arguments...
+#
+# This will take the given source file (must end with
+# ".in"), run sed with the given sed arguments on it, and checks if
+# the result is different from the without the trailing
+# ".in".
+#
+# If this changes the content of , it updates the
+# file and fails the autoreconf run to allow the user to commit the
+# generated file.
+
+set -e
+
+prog="$(basename "$0")"
+
+inname="$1"
+test -n "$inname" || {
+ echo "$prog: error: no source file given" >&2
+ exit 2
+}
+shift
+case "$inname" in
+ *.in)
+ :
+ ;;
+ *)
+ echo "$prog: error: source file name does not end with \".in\": $inname" >&2
+ exit 2
+ ;;
+esac
+test -f "$inname" || {
+ echo "$prog: error: source file is no file: $inname" >&2
+ exit 2
+}
+
+case "$outname" in
+ */*)
+ outname="$(dirname "$inname")/$(basename "$inname" .in)"
+ ;;
+ *)
+ outname="$(basename "$inname" .in)"
+ ;;
+esac
+
+tmqname="$outname.tmq.$$"
+
+${SED-sed} -e "s|^\(.*\)[@]configure_input[@]|\1======================================================================\n\1$outname. Generated from $inname by configure.ac.\n\1======================================================================\n\1!!!!!!! DO NOT MODIFY THIS FILE !!!!!!!!\n\1======================================================================\n\1EDIT $inname INSTEAD AND RE-RUN autoreconf/autogen.sh\n\1======================================================================|g" "$@" < "$inname" > "$tmqname" || {
+ s="$?"
+ echo "$prog: Error running sed, exit code $s." >&2
+ rm -f "$tmqname"
+ exit 2
+}
+
+if grep '[@][A-Za-z0-9_-]\{1,\}@' "$tmqname" >&2; then
+ echo "$prog: Unsubstituted values found while substituting $inname" >&2
+ rm -f "$tmqname"
+ exit 2
+fi
+
+tmpname="$outname.tmp.$$"
+
+cat < "$tmqname" > "$tmpname" || {
+ s="$?"
+ echo "$prog: Error running tr, exit code $s" >&2
+ rm -f "$tmqname"
+ exit 2
+}
+rm -f "$tmqname"
+
+if test -f "$outname"; then
+ if ${CMP-cmp} "$outname" "$tmpname" > /dev/null; then
+ # echo "$prog: source file up to date: $outname" >&2
+ rm -f "$tmpname"
+ ${CHMOD-chmod} a-w "$outname"
+ exit 0
+ else
+ ${DIFF-diff} -u "$outname" "$tmpname" >&2 ||:
+ ${CHMOD-chmod} +w "$outname"
+ mv -f "$tmpname" "$outname"
+ ${CHMOD-chmod} a-w "$outname"
+ echo "$prog: source file has been updated: $outname" >&2
+ echo "$prog: commit the file, and then re-run autoreconf." >&2
+ exit 1
+ fi
+else
+ mv -f "$tmpname" "$outname"
+ ${CHMOD-chmod} a-w "$outname"
+ echo "$prog: created new source file: $outname" >&2
+ echo "$prog: commit the file, and then re-run autoreconf." >&2
+ exit 1
+fi
diff --git a/buildstuff/sed-update-source-file b/buildstuff/sed-update-source-file
new file mode 100755
index 0000000..c076dd3
--- /dev/null
+++ b/buildstuff/sed-update-source-file
@@ -0,0 +1,58 @@
+#! /bin/sh
+#
+# Usage:
+# sed-update-source-file sed-arguments...
+#
+# This will take the given source file , run sed with the
+# given sed commands on it, and if the sed output differs from the
+# input, will update and abort the autoreconf process.
+
+set -e
+
+prog="$(basename "$0")"
+
+fname="$1"
+test -n "$fname" || {
+ echo "$prog: error: no source file given" >&2
+ exit 2
+}
+shift
+test -f "$fname" || {
+ echo "$prog: error: source file is no file: $fname" >&2
+ exit 2
+}
+
+tname="$fname.tmp.$$"
+qname="$fname.tmq.$$"
+
+${SED-sed} "$@" < "$fname" > "$qname" || {
+ s="$?"
+ echo "$prog: Error running sed, exit code $s" >&2
+ rm -f "$qname"
+ exit 2
+}
+
+cat < "$qname" > "$tname" || {
+ s="$?"
+ echo "$prog: Error running tr, exit code $s" >&2
+ rm -f "$qname" "$tname"
+ exit 2
+}
+rm -f "$qname"
+
+test -s "$tname" || {
+ echo "$prog: sed has produced an empty file" >&2
+ exit 2
+}
+
+if ${CMP-cmp} "$fname" "$tname" > /dev/null; then
+ # echo "$prog: source file up to date: $fname" >&2
+ rm -f "$tname"
+ exit 0
+else
+ ${DIFF-diff} -u "$fname" "$tname" >&2 ||:
+ mv -f "$tname" "$fname"
+ echo "$prog: source file has been updated: $fname" >&2
+ echo "$prog: commit the file, and then re-run autoreconf." >&2
+ exit 1
+fi
diff --git a/cmake-config.h.in b/cmake-config.h.in
new file mode 100644
index 0000000..3974528
--- /dev/null
+++ b/cmake-config.h.in
@@ -0,0 +1,18 @@
+/* cmake-config.h.in. Manually generated from config.h.in */
+
+#if 0
+# define SP_PACKAGE_VERSION_MAJOR @SP_PACKAGE_VERSION_MAJOR@
+# define SP_PACKAGE_VERSION_MINOR @SP_PACKAGE_VERSION_MINOR@
+# define SP_PACKAGE_VERSION_MICRO @SP_PACKAGE_VERSION_MICRO@
+# define SP_PACKAGE_VERSION_STRING "@SP_PACKAGE_VERSION_STRING@"
+#endif
+
+#if 0
+# define SP_LIB_VERSION_CURRENT @SP_LIB_VERSION_CURRENT@
+# define SP_LIB_VERSION_AGE @SP_LIB_VERSION_AGE@
+# define SP_LIB_VERSION_REVISION @SP_LIB_VERSION_REVISION@
+# define SP_LIB_VERSION_STRING "@SP_LIB_VERSION_STRING@"
+#endif
+
+#define SP_API @SP_API@
+#define SP_PRIV @SP_PRIV@
diff --git a/configure.ac b/configure.ac
index a26b851..55cc25f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,13 +22,27 @@
AC_PREREQ([2.63])
# libserialport package version number (NOT the same as shared lib version!).
+m4_pattern_forbid([sp_package_])
m4_define([sp_package_version_major], [0])
m4_define([sp_package_version_minor], [1])
m4_define([sp_package_version_micro], [1])
-m4_define([sp_package_version], [sp_package_version_major.sp_package_version_minor.sp_package_version_micro])
+m4_define([sp_package_version_tweak], [23])
+m4_define([sp_package_version], [sp_package_version_major.sp_package_version_minor.sp_package_version_micro]m4_ifdef([sp_package_version_tweak], [.][sp_package_version_tweak]))
-AC_INIT([libserialport], [sp_package_version], [martin-libserialport@earth.li],
- [libserialport], [http://sigrok.org/wiki/Libserialport])
+# Library version for libserialport (NOT the same as the package version).
+# Carefully read the libtool docs before updating these numbers!
+# The algorithm for determining which number to change (and how) is nontrivial!
+# http://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info
+m4_define([sp_lib_version_current], [1])
+m4_define([sp_lib_version_revision], [0])
+m4_define([sp_lib_version_age], [1])
+m4_define([sp_lib_version], [sp_lib_version_current:sp_lib_version_revision:sp_lib_version_age])
+
+AC_INIT([avrdudes bugfix fork of sigrok libserialport],
+ [sp_package_version],
+ [https://github.com/avrdudes/libserialport/issues],
+ [libserialport],
+ [https://github.com/avrdudes/libserialport])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([autostuff])
AC_CONFIG_AUX_DIR([autostuff])
@@ -47,9 +61,23 @@ m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
# Checks for programs.
AC_PROG_CC
+AC_PROG_SED
AC_PROG_INSTALL
AC_PROG_LN_S
+AC_DEFUN([SP_PROG], [dnl
+ m4_assert([$# >= 2])[]dnl
+ AC_ARG_VAR(m4_toupper($1), [$2])
+ AS_VAR_IF(m4_toupper($1), [], [dnl
+ AC_PATH_PROG(m4_toupper($1), [$1], [no])
+ ])
+ AM_CONDITIONAL([HAVE_PROG_]m4_toupper($1), [test "x$m4_toupper($1)" != xno])
+])dnl
+
+SP_PROG([doxygen], [doxygen documentation system])
+SP_PROG([git], [git revision control system])
+
+
## SP_PROG_VERSION(program, sh-var)
## Obtain the version of and store it in .
AC_DEFUN([SP_PROG_VERSION],
@@ -66,26 +94,73 @@ SP_PROG_VERSION([$CC], [sp_cc_version])
# Initialize libtool.
LT_INIT
-AC_DEFINE([SP_PACKAGE_VERSION_MAJOR], [sp_package_version_major], [.])
-AC_DEFINE([SP_PACKAGE_VERSION_MINOR], [sp_package_version_minor], [.])
-AC_DEFINE([SP_PACKAGE_VERSION_MICRO], [sp_package_version_micro], [.])
-AC_DEFINE([SP_PACKAGE_VERSION_STRING], ["sp_package_version"], [.])
+AC_DEFINE_UNQUOTED([SP_PACKAGE_VERSION_MAJOR], [sp_package_version_major], [.])
+AC_DEFINE_UNQUOTED([SP_PACKAGE_VERSION_MINOR], [sp_package_version_minor], [.])
+AC_DEFINE_UNQUOTED([SP_PACKAGE_VERSION_MICRO], [sp_package_version_micro], [.])
+AC_DEFINE_UNQUOTED([SP_PACKAGE_VERSION_STRING], ["sp_package_version"], [.])
AC_SUBST([SP_PACKAGE_VERSION], [sp_package_version])
-# Library version for libserialport (NOT the same as the package version).
-# Carefully read the libtool docs before updating these numbers!
-# The algorithm for determining which number to change (and how) is nontrivial!
-# http://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info
-SP_LIB_VERSION_CURRENT=1
-SP_LIB_VERSION_REVISION=0
-SP_LIB_VERSION_AGE=1
-AC_SUBST([SP_LIB_VERSION],
- ["$SP_LIB_VERSION_CURRENT:$SP_LIB_VERSION_REVISION:$SP_LIB_VERSION_AGE"])
+AC_SUBST([SP_LIB_VERSION], ["sp_lib_version"])
+
+AC_DEFINE_UNQUOTED([SP_LIB_VERSION_CURRENT], [sp_lib_version_current], [.])
+AC_DEFINE_UNQUOTED([SP_LIB_VERSION_REVISION], [sp_lib_version_revision], [.])
+AC_DEFINE_UNQUOTED([SP_LIB_VERSION_AGE], [sp_lib_version_age], [.])
+AC_DEFINE_UNQUOTED([SP_LIB_VERSION_STRING], ["sp_lib_version"], [.])
+
+dnl ------------------------------------------------------------------------
+dnl When necessary, update the libserialport.h source file according
+dnl to changed above sp_package_version* and sp_lib_version* values.
+dnl ------------------------------------------------------------------------
+m4_define([sp_sed_command_args], [])dnl
+m4_define([sp_sed_command_add], [dnl
+ m4_append([sp_sed_command_args],
+ [ -e 's|^\([[:punct:]]define $1\)[[:space:]].*|\1 ]$2[|g'])dnl
+])dnl
+dnl
+sp_sed_command_add([SP_PACKAGE_VERSION_MAJOR], [sp_package_version_major])dnl
+sp_sed_command_add([SP_PACKAGE_VERSION_MINOR], [sp_package_version_minor])dnl
+sp_sed_command_add([SP_PACKAGE_VERSION_MICRO], [sp_package_version_micro])dnl
+sp_sed_command_add([SP_PACKAGE_VERSION_STRING], ["sp_package_version"])dnl
+dnl
+sp_sed_command_add([SP_LIB_VERSION_CURRENT], [sp_lib_version_current])dnl
+sp_sed_command_add([SP_LIB_VERSION_REVISION], [sp_lib_version_revision])dnl
+sp_sed_command_add([SP_LIB_VERSION_AGE], [sp_lib_version_age])dnl
+sp_sed_command_add([SP_LIB_VERSION_STRING], ["sp_lib_version"])dnl
+dnl
+m4_esyscmd([./buildstuff/sed-update-source-file libserialport.h]m4_defn([sp_sed_command_args]))dnl
+m4_case(m4_sysval, [0], [], [dnl
+ m4_fatal([sed-update-source-file script returned non-0])
+])dnl
+
+dnl ------------------------------------------------------------------------
+dnl Generate the CMakeLists.txt file from CMakeLists.txt.in according
+dnl to the above sp_package_version* and sp_lib_version* values.
+dnl ------------------------------------------------------------------------
+m4_define([sp_sed_command_args], [])dnl
+m4_define([sp_sed_command_add], [dnl
+ m4_append([sp_sed_command_args],
+ [ -e 's|[@]]$1[@|]$2[|g'])dnl
+])dnl
+dnl
+sp_sed_command_add([PACKAGE_TARNAME], [AC_PACKAGE_TARNAME])dnl
+sp_sed_command_add([PACKAGE_NAME], [AC_PACKAGE_NAME])dnl
+sp_sed_command_add([PACKAGE_VERSION], [AC_PACKAGE_VERSION])dnl
+sp_sed_command_add([PACKAGE_URL], [AC_PACKAGE_URL])dnl
+dnl
+dnl TODO: Make sure the _minor and _micro values are calculcated correctly.
+m4_define([cmake_lib_version_major], [m4_eval(sp_lib_version_current - sp_lib_version_age)])dnl
+m4_define([cmake_lib_version_minor], [sp_lib_version_age])dnl
+m4_define([cmake_lib_version_micro], [sp_lib_version_revision])dnl
+m4_define([cmake_lib_version], m4_defn([cmake_lib_version_major]).m4_defn([cmake_lib_version_minor]).m4_defn([cmake_lib_version_micro]))dnl
+sp_sed_command_add([CMAKE_LIB_SOVERSION], [cmake_lib_version_major])dnl
+sp_sed_command_add([CMAKE_LIB_VERSION], [cmake_lib_version])dnl
+dnl
+
+m4_esyscmd([./buildstuff/sed-substitute CMakeLists.txt.in]m4_defn([sp_sed_command_args]))dnl
+m4_case(m4_sysval, [0], [], [dnl
+ m4_fatal([sed-substitute script returned non-0])
+])dnl
-AC_DEFINE_UNQUOTED([SP_LIB_VERSION_CURRENT], [$SP_LIB_VERSION_CURRENT], [.])
-AC_DEFINE_UNQUOTED([SP_LIB_VERSION_REVISION], [$SP_LIB_VERSION_REVISION], [.])
-AC_DEFINE_UNQUOTED([SP_LIB_VERSION_AGE], [$SP_LIB_VERSION_AGE], [.])
-AC_DEFINE_UNQUOTED([SP_LIB_VERSION_STRING], ["$SP_LIB_VERSION"], [.])
AM_CONDITIONAL([LINUX], [test -z "${host_os##linux*}" || test -z "${host_os##uclinux*}"])
AM_CONDITIONAL([WIN32], [test -z "${host_os##mingw*}"])
@@ -157,7 +232,7 @@ AS_CASE([$sp_cv_visibility_control],
AC_DEFINE_UNQUOTED([SP_API], [$SP_API], [Macro preceding public API functions])
AC_DEFINE_UNQUOTED([SP_PRIV], [$SP_PRIV], [Macro preceding private functions])
-AC_CONFIG_FILES([Makefile libserialport.pc])
+AC_CONFIG_FILES([Doxyfile Makefile libserialport.pc windows.rc])
AC_OUTPUT
diff --git a/libserialport.h b/libserialport.h
index 7467f74..0c3acf4 100644
--- a/libserialport.h
+++ b/libserialport.h
@@ -33,6 +33,9 @@
*
* libserialport is an open source project released under the LGPL3+ license.
*
+ * **This is a fork of upstream libserialport for integration with avrdude
+ * and fixing bugs and collecting patches to feed back to upstream.**
+ *
* The library is maintained by the [sigrok](http://sigrok.org/) project. See
* the [libserialport homepage](http://sigrok.org/wiki/Libserialport) for the
* latest information.
@@ -1717,7 +1720,7 @@ SP_API void sp_default_debug_handler(const char *format, ...);
#define SP_PACKAGE_VERSION_MICRO 1
/** The libserialport package version ("major.minor.micro") as string. */
-#define SP_PACKAGE_VERSION_STRING "0.1.1"
+#define SP_PACKAGE_VERSION_STRING "0.1.1.23"
/*
* Library/libtool version macros (can be used for conditional compilation).
diff --git a/libserialport_internal.h b/libserialport_internal.h
index f1d0d85..57346d6 100644
--- a/libserialport_internal.h
+++ b/libserialport_internal.h
@@ -158,6 +158,7 @@ struct sp_port {
DWORD write_buf_size;
BOOL writing;
BOOL wait_running;
+ BOOL last_wait_thread_exited;
#else
int fd;
#endif
diff --git a/serialport.c b/serialport.c
index 1135c36..b3b9249 100644
--- a/serialport.c
+++ b/serialport.c
@@ -420,19 +420,35 @@ SP_API void sp_free_port_list(struct sp_port **list)
/** To be called after port receive buffer is emptied. */
static enum sp_return restart_wait(struct sp_port *port)
{
- DWORD wait_result, last_error_code;
+ DWORD wait_result;
if (port->wait_running) {
/* Check status of running wait operation. */
if (GetOverlappedResult(port->hdl, &port->wait_ovl,
&wait_result, FALSE)) {
DEBUG("Previous wait completed");
+ port->last_wait_thread_exited = FALSE;
port->wait_running = FALSE;
- } else if ((last_error_code = GetLastError()) == ERROR_OPERATION_ABORTED) {
- DEBUG("Previous wait aborted");
+ } else if (GetLastError() == ERROR_OPERATION_ABORTED) {
+ /* This error is returned if the last thread that called
+ * restart_wait() has exited while WaitCommEvent() was
+ * still active. In that case we don't consider that to
+ * be an error. Just restart the wait procedure instead.
+ */
+ DEBUG("Previous wait ended due to previous thread exiting");
+ /* We need to record that the wait thread exited before
+ * we called WaitCommEvent(). This is because the exit of
+ * the previous thread always generates a spurious wakeup,
+ * and if no data has been received in the mean time, the
+ * WaitCommEvent() wouldn't be restarted a second time by
+ * restart_wait_if_needed() after a read call after the
+ * spurious wakeup.
+ */
+ port->last_wait_thread_exited = TRUE;
port->wait_running = FALSE;
- } else if (last_error_code == ERROR_IO_INCOMPLETE) {
+ } else if (GetLastError() == ERROR_IO_INCOMPLETE) {
DEBUG("Previous wait still running");
+ port->last_wait_thread_exited = FALSE;
RETURN_OK();
} else {
RETURN_FAIL("GetOverlappedResult() failed");
@@ -1029,7 +1045,11 @@ static enum sp_return restart_wait_if_needed(struct sp_port *port, unsigned int
DWORD errors;
COMSTAT comstat;
- if (bytes_read == 0)
+ /* Only skip restarting the wait operation if we didn't have a
+ * wakeup immediately following the exit of the last thread that
+ * re-initiated the wait loop.
+ */
+ if (!port->last_wait_thread_exited && bytes_read == 0)
RETURN_OK();
if (ClearCommError(port->hdl, &errors, &comstat) == 0)
diff --git a/test-builds.sh b/test-builds.sh
new file mode 100755
index 0000000..47734d4
--- /dev/null
+++ b/test-builds.sh
@@ -0,0 +1,112 @@
+#! /usr/bin/env bash
+#
+# Bash features used:
+# - process substitution: <()
+# - arrays: declare -a
+# - brace globs: {foo,bar}
+
+set -ex
+
+cd "$(dirname "$0")"
+
+rm -rf autom4te.cache
+${AUTORECONF-autoreconf} -vis
+
+find_in_path() {
+ case "$1" in
+ /*)
+ echo "$1"
+ return 0
+ ;;
+ esac
+ local d
+ local saved_IFS
+ saved_IFS="$IFS"
+ IFS=":"
+ for d in $PATH
+ do
+ IFS="$saved_IFS"
+ if test -x "$d/$1"
+ then
+ echo "$d/$1"
+ return 0
+ fi
+ done
+ IFS="$saved_IFS"
+ return 1
+}
+
+for d in _{am,cm}{b,d}{,-w64}
+do
+ test -d "$d" || continue
+ chmod -R +w "$d"
+ rm -rf "$d"
+done
+
+${CMAKE-cmake} -S . -B _cmb -D CMAKE_INSTALL_PREFIX:PATH=/usr/local
+${CMAKE-cmake} --build _cmb --verbose
+${CMAKE-cmake} --build _cmb --target install DESTDIR="$PWD/_cmd"
+
+mkdir _amb
+cd _amb
+declare -a configure_args=()
+if test -d /usr/lib64; then
+ configure_args+=("--libdir=\${exec_prefix}/lib64")
+fi
+../configure --prefix=/usr/local "${configure_args[@]}"
+${MAKE-make} -j$(nproc) V=1
+${MAKE-make} install DESTDIR="$PWD/../_amd"
+cd ..
+
+if find_in_path mingw64-configure && find_in_path mingw64-make
+then
+ mkdir _amb-w64
+ cd _amb-w64
+ mingw64-configure
+ mingw64-make -j$(nproc) V=1
+ mingw64-make install DESTDIR="$PWD/../_amd-w64"
+ cd ..
+fi
+
+have_mingw64=no
+if find_in_path mingw64-cmake
+then
+ have_mingw64=yes
+ mingw64-cmake -S . -B _cmb-w64
+ ${MAKE-make} -C _cmb-w64 -j$(nproc)
+ ${MAKE-make} -C _cmb-w64 install DESTDIR="$PWD/_cmd-w64"
+fi
+
+cd _amb
+if find_in_path ${DOXYGEN-doxygen}
+then
+ ${MAKE-make} -j$(nproc) doc
+fi
+${MAKE-make} -j$(nproc) distcheck
+cd ..
+
+${DIFF-diff} -u \
+ <(find _amd | env LC_ALL=C sort | sed 's|^_amd||') \
+ <(find _cmd | env LC_ALL=C sort | sed 's|^_cmd||') \
+||:
+
+${DIFF-diff} -u _{am,cm}d/lib/pkgconfig/libserialport.pc \
+||:
+
+if test "x$have_mingw64" = xyes
+then
+ ${DIFF-diff} -u \
+ <(find _amd -not -type d | env LC_ALL=C sort | sed 's|^_amd||' | sed 's|^/usr/local||' | sed 's|^/lib64/|/lib/|') \
+ <(find _amd-w64 -not -type d | env LC_ALL=C sort | sed 's|^_amd-w64||' | sed 's|^/usr/x86_64-w64-mingw32/sys-root/mingw||') \
+ ||:
+
+ ${DIFF-diff} -u \
+ <(find _amd-w64 | env LC_ALL=C sort | sed 's|^_amd-w64||') \
+ <(find _cmd-w64 | env LC_ALL=C sort | sed 's|^_cmd-w64||') \
+ ||:
+
+ ${DIFF-diff} -u _{am,cm}d-w64/lib/pkgconfig/libserialport.pc \
+ ||:
+fi
+
+# End of file.
diff --git a/test-visibility-control-attribute.c b/test-visibility-control-attribute.c
new file mode 100644
index 0000000..a8b3414
--- /dev/null
+++ b/test-visibility-control-attribute.c
@@ -0,0 +1 @@
+__attribute__((visibility("hidden"))) void foo(void) {}
diff --git a/test-visibility-control-declspec.c b/test-visibility-control-declspec.c
new file mode 100644
index 0000000..e21aafb
--- /dev/null
+++ b/test-visibility-control-declspec.c
@@ -0,0 +1 @@
+__declspec(dllexport) void foo(void) {}
diff --git a/test_timing.c b/test_timing.c
index a24de5e..febf000 100644
--- a/test_timing.c
+++ b/test_timing.c
@@ -1,4 +1,4 @@
-#include "config.h"
+#include
#include "libserialport.h"
#include "libserialport_internal.h"
#include
@@ -31,7 +31,7 @@ int main(int argc, char *argv[])
time_sub(&b, &a, &c);
printf("Measured: %ums\n", time_as_ms(&c));
assert(time_as_ms(&c) >= 950);
- assert(time_as_ms(&c) <= 1050);
+ assert(time_as_ms(&c) <= 1080);
printf("Starting 3s timeout\n");
timeout_start(&to, 3000);
printf("Time to wait: %dms\n", timeout_remaining_ms(&to));
diff --git a/windows.c b/windows.c
index 2825a92..f894ec5 100644
--- a/windows.c
+++ b/windows.c
@@ -454,8 +454,9 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port)
if (CM_Get_DevNode_Registry_PropertyA(dev_inst, CM_DRP_ADDRESS,
0, &address, &size, 0) == CR_SUCCESS) {
strcpy(tmp, usb_path);
- snprintf(usb_path, sizeof(usb_path), "%d%s%s",
- (int)address, *tmp ? "." : "", tmp);
+ /* FIXME: string length, address value range, etc. */
+ snprintf(usb_path, sizeof(usb_path), "%u%s%s",
+ (BYTE)(0xff & address), *tmp ? "." : "", tmp);
}
} while (CM_Get_Parent(&dev_inst, dev_inst, 0) == CR_SUCCESS);
diff --git a/windows.rc.in b/windows.rc.in
new file mode 100644
index 0000000..47b0e86
--- /dev/null
+++ b/windows.rc.in
@@ -0,0 +1,122 @@
+//
+// avrdude - A Downloader / Uploader for AVR device programmers
+// Copyright(C) 2021 Marius Greuel
+//
+// This program is free software; you can redistribute itand /or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 this program.If not, see < http://www.gnu.org/licenses/>.
+//
+
+#include "winres.h"
+
+#pragma code_page(1252)
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+STRINGTABLE
+BEGIN
+ 100 "LIBSERIALPORT"
+END
+
+#cmakedefine PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
+#ifdef PROJECT_VERSION_MAJOR
+#define VER_MAJOR PROJECT_VERSION_MAJOR
+#else
+#define VER_MAJOR 0
+#endif
+
+#cmakedefine PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@
+#ifdef PROJECT_VERSION_MINOR
+#define VER_MINOR PROJECT_VERSION_MINOR
+#else
+#define VER_MINOR 0
+#endif
+
+#cmakedefine PROJECT_VERSION_PATCH @PROJECT_VERSION_PATCH@
+#ifdef PROJECT_VERSION_PATCH
+#define VER_BUILD PROJECT_VERSION_PATCH
+#else
+#define VER_BUILD 0
+#endif
+
+#cmakedefine PROJECT_VERSION_TWEAK @PROJECT_VERSION_TWEAK@
+#ifdef PROJECT_VERSION_TWEAK
+#define VER_REVISION PROJECT_VERSION_TWEAK
+#else
+#define VER_REVISION 0
+#endif
+
+#cmakedefine GIT_COMMIT_YEAR "@GIT_COMMIT_YEAR@"
+#ifdef GIT_COMMIT_YEAR
+#define VER_COMMIT_YEAR GIT_COMMIT_YEAR
+#else
+#define VER_COMMIT_YEAR ""
+#endif
+
+#define _STR(s) #s
+#define _VER_STR(a, b, c, d) _STR(a) "." _STR(b) "." _STR(c) "." _STR(d)
+
+#define VER_FILEVERSION VER_MAJOR,VER_MINOR,VER_BUILD,VER_REVISION
+#define VER_FILEVERSION_STR _VER_STR(VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION)
+#define VER_PRODUCTVERSION VER_FILEVERSION
+#define VER_PRODUCTVERSION_STR VER_FILEVERSION_STR
+#define VER_COMPANYNAME_STR "The AVRDUDE authors"
+#define VER_FILEDESCRIPTION_STR "AVRDUDE"
+#define VER_PRODUCTNAME_STR "AVRDUDE"
+#define VER_INTERNALNAME_STR "avrdude.exe"
+#define VER_LEGALCOPYRIGHT_STR "\251 " VER_COMMIT_YEAR " The AVRDUDE authors"
+#define VER_ORIGINALFILENAME_STR VER_INTERNALNAME_STR
+#define VER_COMMENTS_STR "@PACKAGE_URL@"
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE 0
+
+#ifdef DEBUG
+#define VER_DEBUG VS_FF_DEBUG
+#else
+#define VER_DEBUG 0
+#endif
+
+#define VER_FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#define VER_FILEOS VOS__WINDOWS32
+#define VER_FILEFLAGS (VER_DEBUG)
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION VER_FILEVERSION
+PRODUCTVERSION VER_PRODUCTVERSION
+FILEFLAGSMASK VER_FILEFLAGSMASK
+FILEFLAGS VER_FILEFLAGS
+FILEOS VER_FILEOS
+FILETYPE VER_FILETYPE
+FILESUBTYPE VER_FILESUBTYPE
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0" // LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP
+ BEGIN
+#ifdef VER_COMMENTS_STR
+ VALUE "Comments", VER_COMMENTS_STR
+#endif
+ VALUE "CompanyName", VER_COMPANYNAME_STR
+ VALUE "FileDescription", VER_FILEDESCRIPTION_STR
+ VALUE "FileVersion", VER_FILEVERSION_STR
+ VALUE "InternalName", VER_INTERNALNAME_STR
+ VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR
+ VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR
+ VALUE "ProductName", VER_PRODUCTNAME_STR
+ VALUE "ProductVersion", VER_PRODUCTVERSION_STR
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0409, 1200 //LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP
+ END
+END