diff --git a/.gitattributes b/.gitattributes
index dfe0770..bf5e415 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,2 +1,5 @@
# Auto detect text files and perform LF normalization
* text=auto
+
+# Never modify line endings of bash scripts
+*.sh text eol=lf
diff --git a/.gitignore b/.gitignore
index 0d6d99e..210056f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,4 @@
#.gitignore
-Sources/.svn
Sources/build_no.h
Trial/.objects
Trial/.vs
@@ -15,19 +14,20 @@ Library/.objects
Library/.vs
Library/x64
Library/x86
-Library/uvslcan
Library/Debug_dll
Library/Debug_lib
Library/Release_dll
Library/Release_lib
+Library/uvslcan
Library/*.so.*
Library/*.dylib
Library/*.sln
Library/*.aps
Library/*.vcxproj.user
slcan-cppcheck-build-dir
+checker.txt
Binaries
Includes
-Tests
+Testing
.vscode
*.log
diff --git a/Library/Makefile b/Library/Makefile
index d7ae13d..39329d3 100644
--- a/Library/Makefile
+++ b/Library/Makefile
@@ -1,7 +1,7 @@
#
# Controller Area Network - Lawicel SLCAN Protocol (Serial-Line CAN)
#
-# Copyright (C) 2016-2024 Uwe Vogt, UV Software, Berlin (info@uv-software.com)
+# Copyright (c) 2016-2024 Uwe Vogt, UV Software, Berlin (info@uv-software.com)
# All rights reserved.
#
# This file is part of SLCAN.
@@ -49,9 +49,21 @@ current_OS := $(patsubst CYGWIN%,Cygwin,$(current_OS))
current_OS := $(patsubst MINGW%,MinGW,$(current_OS))
current_OS := $(patsubst MSYS%,MinGW,$(current_OS))
+MAJOR = 1
+MINOR = 0
+PATCH = 0
+
+ifeq ($(PATCH),0)
+VERSION = $(MAJOR).$(MINOR)
+else
+VERSION = $(MAJOR).$(MINOR).$(PATCH)
+endif
+
HOME_DIR = ..
+MAIN_DIR = .
-SERIAL_DIR = $(HOME_DIR)/Sources
+SOURCE_DIR = $(HOME_DIR)/Sources
+SERIAL_DIR = $(SOURCE_DIR)
OBJECTS = $(OUTDIR)/slcan.o $(OUTDIR)/serial.o \
$(OUTDIR)/buffer.o $(OUTDIR)/queue.o $(OUTDIR)/logger.o
@@ -61,16 +73,11 @@ ifeq ($(current_OS),Darwin) # macOS - libSLCAN.dylib
LIBRARY = libSLCAN
-MAJOR = 0
-MINOR = 1
-PATCH = 0
-
-VERSION = $(MAJOR).$(MINOR).$(PATCH)
TARGET = $(LIBRARY).$(VERSION).dylib
STATIC = $(LIBRARY).a
INSTALL_NAME = $(TARGET)
-CURRENT_VERSION = $(MAJOR).$(MINOR).0
+CURRENT_VERSION = $(MAJOR).$(MINOR).$(PATCH)
COMPATIBILITY_VERSION = $(MAJOR).$(MINOR).0
INSTALL = /usr/local/lib
@@ -81,7 +88,7 @@ DEFINES = -DOPTION_SLCAN_DYLIB=1 \
-DOPTION_SERIAL_DEBUG_LEVEL=0 \
-DOPTION_SLCAN_DEBUG_LEVEL=0
-HEADERS = -I$(SERIAL_DIR) \
+HEADERS = -I$(SOURCE_DIR) \
LIBRARIES = -lpthread
@@ -117,11 +124,6 @@ ifeq ($(current_OS),$(filter $(current_OS),Linux Cygwin)) # linux - libslcan.so.
LIBRARY = libslcan
-MAJOR = 0
-MINOR = 1
-PATCH = 0
-
-VERSION = $(MAJOR).$(MINOR).$(PATCH)
SONAME = $(LIBRARY).so.1
TARGET = $(SONAME).$(VERSION)
STATIC = $(LIBRARY).a
@@ -134,7 +136,7 @@ DEFINES = -DOPTION_SLCAN_SO=1 \
-DOPTION_SERIAL_DEBUG_LEVEL=0 \
-DOPTION_SLCAN_DEBUG_LEVEL=0
-HEADERS = -I$(SERIAL_DIR)
+HEADERS = -I$(SOURCE_DIR)
CFLAGS += -fPIC -O2 -Wall -Wno-parentheses \
-fno-strict-aliasing \
diff --git a/Library/dllmain.cpp b/Library/Sources/dllmain.cpp
similarity index 100%
rename from Library/dllmain.cpp
rename to Library/Sources/dllmain.cpp
diff --git a/Library/framework.h b/Library/Sources/framework.h
similarity index 100%
rename from Library/framework.h
rename to Library/Sources/framework.h
diff --git a/Library/pch.cpp b/Library/Sources/pch.cpp
similarity index 100%
rename from Library/pch.cpp
rename to Library/Sources/pch.cpp
diff --git a/Library/pch.h b/Library/Sources/pch.h
similarity index 100%
rename from Library/pch.h
rename to Library/Sources/pch.h
diff --git a/Library/resource.h b/Library/Sources/resource.h
similarity index 100%
rename from Library/resource.h
rename to Library/Sources/resource.h
diff --git a/Library/uvslcan.rc b/Library/uvslcan.rc
index 64d0f2d..ce604af 100644
Binary files a/Library/uvslcan.rc and b/Library/uvslcan.rc differ
diff --git a/Library/uvslcan.vcxproj b/Library/uvslcan.vcxproj
index 281e16f..33bfa5d 100644
--- a/Library/uvslcan.vcxproj
+++ b/Library/uvslcan.vcxproj
@@ -132,7 +132,7 @@
trueUsepch.h
- ..\Sources;%(AdditionalIncludeDirectories)
+ .\Sources;..\Sources;%(AdditionalIncludeDirectories)Windows
@@ -148,7 +148,7 @@
trueUsepch.h
- ..\Sources;%(AdditionalIncludeDirectories)
+ .\Sources;..\Sources;%(AdditionalIncludeDirectories)Windows
@@ -166,7 +166,7 @@
trueUsepch.h
- ..\Sources;%(AdditionalIncludeDirectories)
+ .\Sources;..\Sources;%(AdditionalIncludeDirectories)Windows
@@ -186,7 +186,7 @@
trueUsepch.h
- ..\Sources;%(AdditionalIncludeDirectories)
+ .\Sources;..\Sources;%(AdditionalIncludeDirectories)Windows
@@ -204,7 +204,7 @@
trueUsepch.h
- ..\Sources;%(AdditionalIncludeDirectories)
+ .\Sources;..\Sources;%(AdditionalIncludeDirectories)Windows
@@ -220,7 +220,7 @@
trueUsepch.h
- ..\Sources;%(AdditionalIncludeDirectories)
+ .\Sources;..\Sources;%(AdditionalIncludeDirectories)Windows
@@ -238,7 +238,7 @@
trueUsepch.h
- ..\Sources;%(AdditionalIncludeDirectories)
+ .\Sources;..\Sources;%(AdditionalIncludeDirectories)Windows
@@ -258,7 +258,7 @@
trueUsepch.h
- ..\Sources;%(AdditionalIncludeDirectories)
+ .\Sources;..\Sources;%(AdditionalIncludeDirectories)Windows
@@ -276,9 +276,9 @@
-
-
-
+
+
+
@@ -331,8 +331,8 @@
NotUsingNotUsing
-
-
+
+ CreateCreateCreate
diff --git a/Library/uvslcan.vcxproj.filters b/Library/uvslcan.vcxproj.filters
index d3912ad..6b07230 100644
--- a/Library/uvslcan.vcxproj.filters
+++ b/Library/uvslcan.vcxproj.filters
@@ -15,10 +15,10 @@
-
+ Header Files
-
+ Header Files
@@ -42,15 +42,15 @@
Header Files
-
+ Header Files
-
+ Source Files
-
+ Source Files
diff --git a/Makefile b/Makefile
index f06bf36..4ff9a1e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
#
# Controller Area Network - Lawicel SLCAN Protocol (Serial-Line CAN)
#
-# Copyright (C) 2016-2024 Uwe Vogt, UV Software, Berlin (info@uv-software.com)
+# Copyright (c) 2016-2024 Uwe Vogt, UV Software, Berlin (info@uv-software.com)
# All rights reserved.
#
# This file is part of SLCAN.
diff --git a/README.md b/README.md
index 16adc00..f86f635 100644
--- a/README.md
+++ b/README.md
@@ -10,378 +10,107 @@ Implementation of Lawicel SLCAN protocol.
## SLCAN API
```C
-/** @brief creates a port instance for communication with a SLCAN compatible
- * serial device (constructor).
- *
- * @param[in] queueSize - size of the reception queue (number of messages)
- *
- * @returns a pointer to a SLCAN instance if successful, or NULL on error.
- *
- * @note System variable 'errno' will be set in case of an error.
- *
- * @retval ENOMEM - out of memory (insufficient storage space)
- */
-SLCANAPI slcan_port_t slcan_create(size_t queueSize);
-
-
-/** @brief destroys the port instance (destructor).
- *
- * @remarks An established connection will be terminated by this.
- *
- * @remarks Prior to this the CAN controller is set into INIT mode and
- * the CAN channel is closed (via command 'Close Channel').
- *
- * @param[in] port - pointer to a SLCAN instance
- *
- * @returns 0 if successful, or a negative value on error.
- *
- * @note System variable 'errno' will be set in case of an error.
- *
- * @retval ENODEV - no such device (invalid port instance)
- * @retval EFAULT - bad address (release of resources)
- */
-SLCANAPI slcan_destroy(slcan_port_t port);
-
-
-/** @brief establishes a connection with the serial communication device.
- *
- * @remarks The SLCAN protocol is check by retrieving version information
- * of the CAN channel (via command 'HW/SW Version').
- *
- * @remarks Precautionary the CAN controller is set into INIT mode and
- * the CAN channel is closed (via command 'Close Channel').
- *
- * @param[in] port - pointer to a SLCAN instance
- * @param[in] device - name of the serial device
- * @param[in] attr - serial port attributes (optional)
- *
- * @returns a file descriptor if successful, or a negative value on error.
- *
- * @remarks On Windows, the communication port number (zero based) is returned.
- *
- * @note System variable 'errno' will be set in case of an error.
- *
- * @retval ENODEV - no such device (invalid port instance)
- * @retval EINVAL - invalid argument (device name is NULL)
- * @retval EALREADY - already connected with the serial device
- * @retval 'errno' - error code from called system functions:
- * 'open', 'tcsetattr', 'pthread_create'
- */
-SLCANAPI slcan_connect(slcan_port_t port, const char *device, const sio_attr_t *attr);
-
-
-/** @brief terminates the connection with the serial communication device.
- *
- * @remarks Prior to this the CAN controller is set into INIT mode and
- * the CAN channel is closed (via command 'Close Channel').
- *
- * @param[in] port - pointer to a SLCAN instance
- *
- * @returns 0 if successful, or a negative value on error.
- *
- * @note System variable 'errno' will be set in case of an error.
- *
- * @retval ENODEV - no such device (invalid port instance)
- * @retval EBADF - bad file descriptor (device not connected)
- * @retval 'errno' - error code from called system functions:
- * 'pthread_cancel', 'tcflush', 'close'
- */
-SLCANAPI slcan_disconnect(slcan_port_t port);
-
-
-/** @brief returns the serial communication attributes (baudrate, etc.).
- *
- * @param[in] port - pointer to a SLCAN instance
- * @param[out] attr - serial communication attributes
- *
- * @returns 0 if successful, or a negative value on error.
- *
- * @note System variable 'errno' will be set in case of an error.
- *
- * @retval ENODEV - no such device (invalid port instance)
- * @retval EINVAL - invalid argument (attr is NULL)
- */
-SLCANAPI slcan_get_attr(slcan_port_t port, slcan_attr_t *attr);
-
-
-/** @brief setup with standard CAN bit-rates.
- *
- * @remarks This command is only active if the CAN channel is closed.
- *
- * @param[in] port - pointer to a SLCAN instance
- * @param[in] index -
- *
- * @returns 0 if successful, or a negative value on error.
- *
- * @note System variable 'errno' will be set in case of an error.
- *
- * @retval ENODEV - no such device (invalid port instance)
- * @retval EINVAL - invalid argument (index)
- * @retval EBADF - bad file descriptor (device not connected)
- * @retval EBUSY - device / resource busy (disturbance)
- * @retval EBADMSG - bad message (format or disturbance)
- * @retval ETIMEDOUT - timed out (command not acknowledged)
- * @retval 'errno' - error code from called system functions:
- * 'write', 'read', etc.
- */
-SLCANAPI slcan_setup_bitrate(slcan_port_t port, uint8_t index);
-
-
-/** @brief setup with BTR0/BTR1 CAN bit-rates; see SJA1000 datasheet.
- *
- * @remarks This command is only active if the CAN channel is closed.
- *
- * @param[in] port - pointer to a SLCAN instance
- * @param[in] btr - SJA1000 bit-timing register
- *
- * @returns 0 if successful, or a negative value on error.
- *
- * @note System variable 'errno' will be set in case of an error.
- *
- * @retval ENODEV - no such device (invalid port instance)
- * @retval EINVAL - invalid argument (...)
- * @retval EBADF - bad file descriptor (device not connected)
- * @retval EBUSY - device / resource busy (disturbance)
- * @retval EBADMSG - bad message (format or disturbance)
- * @retval ETIMEDOUT - timed out (command not acknowledged)
- * @retval 'errno' - error code from called system functions:
- * 'write', 'read', etc.
- */
-SLCANAPI slcan_setup_btr(slcan_port_t port, uint16_t btr);
-
-
-/** @brief opens the CAN channel.
- *
- * @remarks This command is only active if the CAN channel is closed and
- * has been set up prior with either the 'Setup Bitrate' or
- * 'Setup BTR' command (i.e. initiated).
- *
- * @param[in] port - pointer to a SLCAN instance
- *
- * @returns 0 if successful, or a negative value on error.
- *
- * @note System variable 'errno' will be set in case of an error.
- *
- * @retval ENODEV - no such device (invalid port instance)
- * @retval EINVAL - invalid argument (...)
- * @retval EBADF - bad file descriptor (device not connected)
- * @retval EBUSY - device / resource busy (disturbance)
- * @retval EBADMSG - bad message (format or disturbance)
- * @retval ETIMEDOUT - timed out (command not acknowledged)
- * @retval 'errno' - error code from called system functions:
- * 'write', 'read', etc.
- */
-SLCANAPI slcan_open_channel(slcan_port_t port);
-
-
-/** @brief closes the CAN channel.
- *
- * @remarks This command is only active if the CAN channel is open.
- *
- * @param[in] port - pointer to a SLCAN instance
- *
- * @returns 0 if successful, or a negative value on error.
- *
- * @note System variable 'errno' will be set in case of an error.
- *
- * @retval ENODEV - no such device (invalid port instance)
- * @retval EINVAL - invalid argument (...)
- * @retval EBADF - bad file descriptor (device not connected)
- * @retval EBUSY - device / resource busy (disturbance)
- * @retval EBADMSG - bad message (format or disturbance)
- * @retval ETIMEDOUT - timed out (command not acknowledged)
- * @retval 'errno' - error code from called system functions:
- * 'write', 'read', etc.
- */
-SLCANAPI slcan_close_channel(slcan_port_t port);
-
-
-/** @brief transmits a CAN message.
- *
- * @remarks This command is only active if the CAN channel is open.
- *
- * @param[in] port - pointer to a SLCAN instance
- * @param[in] message - pointer to the message to be sent
- * @param[in] timeout - (not implemented yet)
- *
- * @returns 0 if successful, or a negative value on error.
- *
- * @note System variable 'errno' will be set in case of an error.
- *
- * @retval ENODEV - no such device (invalid port instance)
- * @retval EINVAL - invalid argument (message)
- * @retval EBADF - bad file descriptor (device not connected)
- * @retval EBUSY - device / resource busy (disturbance)
- * @retval EBADMSG - bad message (format or disturbance)
- * @retval ETIMEDOUT - timed out (command not acknowledged)
- * @retval 'errno' - error code from called system functions:
- * 'write', 'read', etc.
- */
-SLCANAPI slcan_write_message(slcan_port_t port, const slcan_message_t *message, uint16_t timeout);
-
-
-/** @brief read one message from the message queue, if any.
- *
- * @param[in] port - pointer to a SLCAN instance
- * @param[out] message - pointer to a message buffer
- * @param[in] timeout - time to wait for the reception of a message:
- * 0 means the function returns immediately,
- * 65535 means blocking read, and any other
- * value means the time to wait im milliseconds
- *
- * @returns 0 if successful, or a negative value on error.
- *
- * @retval -30 - when the message queue is empty (CAN API compatible)
- *
- * @note System variable 'errno' will be set in case of an error.
- *
- * @retval ENODEV - no such device (invalid port instance)
- * @retval EINVAL - invalid argument (message)
- * @retval ENOMSG - no data available (message queue empty)
- * @retval ENOSPC - no space left (message queue overflow)
- *
- * @remarks If a message has been successfully read from the message queue,
- * the value ENOSPC in the system variable 'errno' indicates that
- * a message queue overflow has occurred and that at least one
- * CAN message has been lost.
- */
-SLCANAPI slcan_read_message(slcan_port_t port, slcan_message_t *message, uint16_t timeout);
-
-
-/** @brief read status flags.
- *
- * @remarks This command is only active if the CAN channel is open.
- *
- * @param[in] port - pointer to a SLCAN instance
- * @param[out] flags - channel status flags
- *
- * @returns 0 if successful, or a negative value on error.
- *
- * @note System variable 'errno' will be set in case of an error.
- *
- * @retval ENODEV - no such device (invalid port instance)
- * @retval EBADF - bad file descriptor (device not connected)
- * @retval EBUSY - device / resource busy (disturbance)
- * @retval EBADMSG - bad message (format or disturbance)
- * @retval ETIMEDOUT - timed out (command not acknowledged)
- * @retval 'errno' - error code from called system functions:
- * 'write', 'read', etc.
- */
-SLCANAPI slcan_status_flags(slcan_port_t port, slcan_flags_t *flags);
-
-
-/** @brief sets Acceptance Code Register (ACn Register of SJA1000).
- *
- * @remarks This command is only active if the CAN channel is initiated
- * and not opened.
- *
- * @param[in] port - pointer to a SLCAN instance
- * @param[in] code - acceptance code register
- *
- * @returns 0 if successful, or a negative value on error.
- *
- * @note System variable 'errno' will be set in case of an error.
- *
- * @retval ENODEV - no such device (invalid port instance)
- * @retval EBADF - bad file descriptor (device not connected)
- * @retval EBUSY - device / resource busy (disturbance)
- * @retval EBADMSG - bad message (format or disturbance)
- * @retval ETIMEDOUT - timed out (command not acknowledged)
- * @retval 'errno' - error code from called system functions:
- * 'write', 'read', etc.
- */
-SLCANAPI slcan_acceptance_code(slcan_port_t port, uint32_t code);
-
-
-/** @brief sets Acceptance Mask Register (AMn Register of SJA1000).
- *
- * @remarks This command is only active if the CAN channel is initiated
- * and not opened.
- *
- * @param[in] port - pointer to a SLCAN instance
- * @param[in] mask - acceptance mask register
- *
- * @returns 0 if successful, or a negative value on error.
- *
- * @note System variable 'errno' will be set in case of an error.
- *
- * @retval ENODEV - no such device (invalid port instance)
- * @retval EBADF - bad file descriptor (device not connected)
- * @retval EBUSY - device / resource busy (disturbance)
- * @retval EBADMSG - bad message (format or disturbance)
- * @retval ETIMEDOUT - timed out (command not acknowledged)
- * @retval 'errno' - error code from called system functions:
- * 'write', 'read', etc.
- */
-SLCANAPI slcan_acceptance_mask(slcan_port_t port, uint32_t mask);
-
-
-/** @brief get version number of both SLCAN hardware and software.
- *
- * @remarks This command is active always.
- *
- * @param[in] port - pointer to a SLCAN instance
- * @param[out] hardware - hardware version (8-bit: .)
- * @param[out] software - software version (8-bit: .)
- *
- * @returns 0 if successful, or a negative value on error.
- *
- * @note System variable 'errno' will be set in case of an error.
- *
- * @retval ENODEV - no such device (invalid port instance)
- * @retval EBADF - bad file descriptor (device not connected)
- * @retval EBUSY - device / resource busy (disturbance)
- * @retval EBADMSG - bad message (format or disturbance)
- * @retval ETIMEDOUT - timed out (command not acknowledged)
- * @retval 'errno' - error code from called system functions:
- * 'write', 'read', etc.
- */
-SLCANAPI slcan_version_number(slcan_port_t port, uint8_t *hardware, uint8_t *software);
-
-
-/** @brief get serial number of the SLCAN device.
- *
- * @remarks This command is active always.
- *
- * @param[in] port - pointer to a SLCAN instance
- * @param[out] number - serial number (32-bit: 8 bytes)
- *
- * @returns 0 if successful, or a negative value on error.
- *
- * @note System variable 'errno' will be set in case of an error.
- *
- * @retval ENODEV - no such device (invalid port instance)
- * @retval EBADF - bad file descriptor (device not connected)
- * @retval EBUSY - device / resource busy (disturbance)
- * @retval EBADMSG - bad message (format or disturbance)
- * @retval ETIMEDOUT - timed out (command not acknowledged)
- * @retval 'errno' - error code from called system functions:
- * 'write', 'read', etc.
- */
-SLCANAPI slcan_serial_number(slcan_port_t port, uint32_t *number);
-
-
-/** @brief signal all waiting objects, if any.
- *
- * @param[in] port - pointer to a SLCAN instance
- *
- * @returns 0 if successful, or a negative value on error.
- */
-SLCANAPI slcan_signal(slcan_port_t port);
-
-
-/** @brief retrieves version information of the SLCAN API as a
- * zero-terminated string.
- *
- * @param[out] version_no - major and minor version number (optional)
- * @param[out] patch_no - patch number (optional)
- * @param[out] build_no - build number (optional)
- *
- * @returns pointer to a zero-terminated string, or NULL on error.
- */
-SLCANAPI char *slcan_api_version(uint16_t *version_no, uint8_t *patch_no, uint32_t *build_no);
+slcan_port_t slcan_create(size_t queueSize);
+int slcan_destroy(slcan_port_t port);
+int slcan_connect(slcan_port_t port, const char *device, const sio_attr_t *attr);
+int slcan_disconnect(slcan_port_t port);
+int slcan_get_attr(slcan_port_t port, slcan_attr_t *attr);
+int slcan_setup_bitrate(slcan_port_t port, uint8_t index);
+int slcan_setup_btr(slcan_port_t port, uint16_t btr);
+int slcan_open_channel(slcan_port_t port);
+int slcan_close_channel(slcan_port_t port);
+int slcan_write_message(slcan_port_t port, const slcan_message_t *message, uint16_t timeout);
+int slcan_read_message(slcan_port_t port, slcan_message_t *message, uint16_t timeout);
+int slcan_status_flags(slcan_port_t port, slcan_flags_t *flags);
+int slcan_acceptance_code(slcan_port_t port, uint32_t code);
+int slcan_acceptance_mask(slcan_port_t port, uint32_t mask);
+int slcan_version_number(slcan_port_t port, uint8_t *hardware, uint8_t *software);
+int slcan_serial_number(slcan_port_t port, uint32_t *number);
+int slcan_signal(slcan_port_t port);
+char *slcan_api_version(uint16_t *version_no, uint8_t *patch_no, uint32_t *build_no);
```
+### Build Targets
+
+_Important note_: To build any of the following build targets run the `build_no.sh` script to generate a pseudo build number.
+```
+gonggomg@uv-pc015deb:~$ cd ~/Projects/CAN/SLCAN
+gonggomg@uv-pc015deb:~/Projects/CAN/SLCAN$ ./build_no.sh
+```
+Repeat this step after each `git commit`, `git pull`, `git clone`, etc.
+
+Then you can build the whole _bleep_ by typing the usual commands:
+```
+gonggomg@uv-pc015deb:~$ cd ~/Projects/CAN/SLCAN
+gonggomg@uv-pc015deb:~/Projects/CAN/SLCAN$ make clean
+gonggomg@uv-pc015deb:~/Projects/CAN/SLCAN$ make all
+gonggomg@uv-pc015deb:~/Projects/CAN/SLCAN$ sudo make install
+```
+_(The version number of the libraries can be adapted by editing the `Makefile`s in the subfolders and changing the variable `VERSION` accordingly. DonĀ“t forget to set the version number also in the source files.)_
+
+#### libSLCAN
+
+___libSLCAN___ is a dynamic library with a basic SLCAN application programming interface for use in __C__ applications.
+See header file `slcan.h` for a description of all API functions.
+
+### Target Platforms
+
+POSIX® compatible operating systems:
+
+1. macOS®
+1. Linux®
+1. Cygwin®
+
+Windows® (x64 operating system):
+
+1. Windows 10 Pro
+1. Windows 11 Pro
+
+### Development Environments
+
+#### macOS Sonoma
+
+- macOS Sonoma (14.4) on a Mac mini (M1, 2020)
+- Apple clang version 15.0.0 (clang-1500.3.9.4)
+- Xcode Version 15.3 (15E204a)
+
+#### macOS Monterey
+
+- macOS Monterey (12.7.4) on a MacBook Pro (2019)
+- Apple clang version 13.0.0 (clang-1300.0.29.30)
+- Xcode Version 13.2.1 (13C100)
+
+#### macOS High Sierra
+
+- macOS High Sierra (10.13.6) on a MacBook Pro (late 2011)
+- Apple LLVM version 10.0.0 (clang-1000.11.45.5)
+- Xcode Version 10.1 (10B61)
+
+#### Debian Bullseye (11.2)
+
+- Debian 4.19.160-2 (2020-11-18) x86_64 GNU/Linux
+- gcc (Debian 10.2.1-6) 10.2.1 20210110
+
+#### Cygwin (64-bit)
+
+- Cygwin 3.5.1-1.x86_64 under Windows 10 Pro
+- GNU C/C++ Compiler (GCC) 11.4.0
+
+#### Windows 10 & 11
+
+- Microsoft Visual Studio Community 2022 (Version 17.9.4)
+
+### CAN Hardware
+
+- Lawicel CANUSB (Hardware 1.0, Firmware 1.1)
+
+## Known Bugs and Caveats
+
+1. Transmitting messages over the TTY is extremely slow; approx. 16ms per frame.
+ I guess this is because the transmission is acknowledged by the CAN device.
+
+2. Time-stamps are currently not supported.
+
## This and That
The documentation of the SLCAN protocol can be found on [Lawicel CANUSB product page](https://www.canusb.com/products/canusb).
@@ -401,6 +130,10 @@ POSIX is a registered of the Institute of Electrical and Electronic Engineers, I
Linux is a registered trademark of Linus Torvalds. \
All other company, product and service names mentioned herein may be trademarks, registered trademarks, or service marks of their respective owners.
+### Hazard Note
+
+_If you connect your CAN device to a real CAN network when using this library, you might damage your application._
+
### Contact
E-Mail: mailto://info@uv-software.com \
diff --git a/Sources/serial_w.c b/Sources/serial_w.c
index 33798a1..acfbda3 100644
--- a/Sources/serial_w.c
+++ b/Sources/serial_w.c
@@ -51,7 +51,7 @@
*
* @author $Author: haumea $
*
- * @version $Rev: 803 $
+ * @version $Rev: 807 $
*
* @addtogroup serial
* @{
@@ -238,9 +238,9 @@ int sio_connect(sio_port_t port, const char *device, const sio_attr_t *attr) {
#if defined(_UNICODE)
if ((serial->hPort = CreateFileA(path, (GENERIC_READ | GENERIC_WRITE),
#else
- if ((serial->hPort = CreateFileW(path, (GENERIC_READ | GENERIC_WRITE),
+ if ((serial->hPort = CreateFile(path, (GENERIC_READ | GENERIC_WRITE),
#endif
- 0, // exclusive access
+ 0, // exclusive access
NULL, // no security attrs
OPEN_EXISTING, // default for devices other than files
0, // flags: no overlapped I/O
diff --git a/Sources/slcan.c b/Sources/slcan.c
index e84b131..9d92896 100644
--- a/Sources/slcan.c
+++ b/Sources/slcan.c
@@ -47,19 +47,16 @@
*
* @brief Lawicel SLCAN protocol.
*
- * @author $Author: haumea $
+ * @author $Author: quaoar $
*
- * @version $Rev: 805 $
+ * @version $Rev: 808 $
*
* @addtogroup slcan
* @{
*/
-#include "build_no.h"
-#define VERSION_MAJOR 0
-#define VERSION_MINOR 1
-#define VERSION_PATCH 99
-#define VERSION_BUILD BUILD_NO
-#define VERSION_STRING TOSTRING(VERSION_MAJOR) "." TOSTRING(VERSION_MINOR) "." TOSTRING(VERSION_PATCH) " (" TOSTRING(BUILD_NO) ")"
+#define VERSION_MAJOR 1
+#define VERSION_MINOR 0
+#define VERSION_PATCH 0
#if defined(_WIN64)
#define PLATFORM "x64"
#elif defined(_WIN32)
@@ -73,8 +70,17 @@
#else
#error Platform not supported
#endif
-static const char version[] = "Lawicel SLCAN Protocol (Serial-Line CAN), Version " VERSION_STRING;
-
+#if (VERSION_PATCH == 0)
+static const char version[] = "Lawicel SLCAN Protocol (Serial-Line CAN), Version %i.%i (%u)";
+#else
+static const char version[] = "Lawicel SLCAN Protocol (Serial-Line CAN), Version %i.%i.%i (%u)";
+#endif
+#ifdef _MSC_VER
+//no Microsoft extensions please!
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS 1
+#endif
+#endif
/* ----------- includes -----------------------------------------------
*/
@@ -780,15 +786,31 @@ int slcan_serial_number(slcan_port_t port, uint32_t *number) {
EXPORT
char *slcan_api_version(uint16_t *version_no, uint8_t *patch_no, uint32_t *build_no) {
- SLCAN_DEBUG_INFO("%s\n", version);
+ static char str[100 + 1] = "Try to relaxe and enjoy the crisis.";
+ const char svn[17 + 1] = "$Rev: 808 $";
+ unsigned rev = 0u;
+ /* determine pseudo build no. from SVN revision */
+ if (sscanf(svn, "$Rev: %u", &rev) != 1)
+ rev = 99u;
+
+ /* numerical version information are optional */
if (version_no)
*version_no = ((uint16_t)VERSION_MAJOR << 8) | (uint16_t)VERSION_MINOR;
if (patch_no)
*patch_no = (uint8_t)VERSION_PATCH;
if (build_no)
- *build_no = (uint32_t)VERSION_BUILD;
- return (char*)version;
+ *build_no = (uint32_t)rev;
+
+ /* return the version as zero-terminated string */
+#if (VERSION_PATCH != 0)
+ snprintf(str, 100, version, VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, rev);
+#else
+ snprintf(str, 100, version, VERSION_MAJOR, VERSION_MINOR, rev);
+#endif
+ str[100] = '\0';
+ SLCAN_DEBUG_INFO("slcan_api_version (%s)\n", str);
+ return (char*)str;
}
static int send_command(slcan_t *slcan, const uint8_t *request, size_t nbytes,
diff --git a/Sources/slcan.h b/Sources/slcan.h
index 9102079..3d55697 100644
--- a/Sources/slcan.h
+++ b/Sources/slcan.h
@@ -47,9 +47,9 @@
*
* @brief Lawicel SLCAN protocol.
*
- * @author $Author: haumea $
+ * @author $Author: quaoar $
*
- * @version $Rev: 805 $
+ * @version $Rev: 808 $
*
* @defgroup slcan Lawicel SLCAN Protocol
* @{
@@ -79,7 +79,7 @@
#else
#define SLCANAPI extern
#endif
- /** @} */
+/** @} */
/* ----------- defines ------------------------------------------------
*/
diff --git a/Trial/Makefile b/Trial/Makefile
index e7da543..8fbad87 100644
--- a/Trial/Makefile
+++ b/Trial/Makefile
@@ -20,7 +20,8 @@ INSTALL = ~/bin
HOME_DIR = ..
MAIN_DIR = ./Sources
-SERIAL_DIR = $(HOME_DIR)/Sources
+SOURCE_DIR = $(HOME_DIR)/Sources
+SERIAL_DIR = $(SOURCE_DIR)
OBJECTS = $(OUTDIR)/slcan.o $(OUTDIR)/serial.o \
$(OUTDIR)/buffer.o $(OUTDIR)/queue.o $(OUTDIR)/logger.o \
@@ -29,7 +30,7 @@ OBJECTS = $(OUTDIR)/slcan.o $(OUTDIR)/serial.o \
DEFINES = -DOPTION_SERIAL_DEBUG_LEVEL=1 \
-DOPTION_SLCAN_DEBUG_LEVEL=1
-HEADERS = -I$(SERIAL_DIR) \
+HEADERS = -I$(SOURCE_DIR) \
-I$(MAIN_DIR)
LIBRARIES = -lpthread
@@ -53,7 +54,7 @@ LDFLAGS += -arch arm64 -arch x86_64
endif
CHECKER = warning,information
-IGNORE = -i can_msg.c -i can_dev.c
+IGNORE = -i *_w.c
ifeq ($(HUNTER),BUGS)
CHECKER += --bug-hunting
endif
@@ -62,7 +63,7 @@ ifeq ($(current_OS),Darwin) # macOS - libSLCAN.dylib
CXX = clang++
CC = clang
LD = clang++
-else # Linux, Cygwin - libSLCAN.so
+else # Linux, Cygwin - libslcan.so
CXX = g++
CC = gcc
LD = g++
diff --git a/build_no.bat b/build_no.bat
index 6dc1616..9ed6dec 100644
--- a/build_no.bat
+++ b/build_no.bat
@@ -3,7 +3,7 @@ echo /* -- Do not commit this file -- > Sources/build_no.h
echo * >> Sources/build_no.h
echo * Controller Area Network - Lawicel SLCAN Protocol (Serial-Line CAN) >> Sources/build_no.h
echo * >> Sources/build_no.h
-echo * Copyright (C) 2016-2024 Uwe Vogt, UV Software, Berlin (info@uv-software.com) >> Sources/build_no.h
+echo * Copyright (c) 2016-2024 Uwe Vogt, UV Software, Berlin (info@uv-software.com) >> Sources/build_no.h
echo * All rights reserved. >> Sources/build_no.h
echo * >> Sources/build_no.h
echo * This file is part of SLCAN. >> Sources/build_no.h
diff --git a/build_no.sh b/build_no.sh
index 3325a54..6c5a343 100755
--- a/build_no.sh
+++ b/build_no.sh
@@ -3,7 +3,7 @@ echo "/* -- Do not commit this file --" > ./Sources/build_no.h
echo " *" >> ./Sources/build_no.h
echo " * Controller Area Network - Lawicel SLCAN Protocol (Serial-Line CAN)" >> ./Sources/build_no.h
echo " *" >> ./Sources/build_no.h
-echo " * Copyright (C) 2016-2022 Uwe Vogt, UV Software, Berlin (info@uv-software.com)" >> ./Sources/build_no.h
+echo " * Copyright (c) 2016-2022 Uwe Vogt, UV Software, Berlin (info@uv-software.com)" >> ./Sources/build_no.h
echo " * All rights reserved." >> ./Sources/build_no.h
echo " *" >> ./Sources/build_no.h
echo " * This file is part of SLCAN." >> ./Sources/build_no.h
diff --git a/x64_install.bat b/x64_install.bat
index 6577da2..8a38819 100644
--- a/x64_install.bat
+++ b/x64_install.bat
@@ -2,7 +2,7 @@
set PWD="%~dp0"
pushd
cd /D %PWD%
-copy /Y .\Libraries\CANAPI\x64\Release_dll\uvslcan.dll C:\Windows\System32
+copy /Y .\Library\x64\Release_dll\uvslcan.dll C:\Windows\System32
popd
dir C:\Windows\System32\u*can*.dll
pause
diff --git a/x86_install.bat b/x86_install.bat
index 570e541..9db8aed 100644
--- a/x86_install.bat
+++ b/x86_install.bat
@@ -2,7 +2,7 @@
set PWD="%~dp0"
pushd
cd /D %PWD%
-copy /Y .\Libraries\CANAPI\Release_dll\uvslcan.dll C:\Windows\SysWOW64
+copy /Y .\Library\Release_dll\uvslcan.dll C:\Windows\SysWOW64
popd
dir C:\Windows\SysWOW64\u*can*.dll
pause