From 4edff5d0e3590952e7bffe8724cdeb632d191134 Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Thu, 9 Jan 2020 19:43:08 -0500 Subject: [PATCH 01/21] Automatically detect Microsoft Visual Studio NMAKE vs. GNU make For the best user experience, typing "nmake" in the Microsoft Visual Studio Developer Command Prompt should build the Wirepas C Mesh API library successfully. The syntax of NMAKE and GNU make makefiles are sufficiently different that a single makefile will not work for both. This commit adds automatic detection of the make tool in use, and calls the suitable tool-dependent makefile. Working NMAKE makefiles will be added in another commit. --- example/gnu_make.mk | 87 ++++++++++++++++ example/makefile | 130 ++++++++--------------- lib/gnu_make.mk | 84 +++++++++++++++ lib/makefile | 127 ++++++++--------------- lib/nmake.mk | 1 + lib/platform/{makefile => gnu_make.mk} | 0 lib/platform/nmake.mk | 1 + lib/wpc/{makefile => gnu_make.mk} | 2 +- lib/wpc/nmake.mk | 1 + test/gnu_make.mk | 94 +++++++++++++++++ test/makefile | 137 ++++++++----------------- 11 files changed, 398 insertions(+), 266 deletions(-) create mode 100644 example/gnu_make.mk create mode 100644 lib/gnu_make.mk create mode 100644 lib/nmake.mk rename lib/platform/{makefile => gnu_make.mk} (100%) create mode 100644 lib/platform/nmake.mk rename lib/wpc/{makefile => gnu_make.mk} (89%) create mode 100644 lib/wpc/nmake.mk create mode 100644 test/gnu_make.mk diff --git a/example/gnu_make.mk b/example/gnu_make.mk new file mode 100644 index 0000000..924d13a --- /dev/null +++ b/example/gnu_make.mk @@ -0,0 +1,87 @@ +# Makefile for Wirepas C Mesh API example, GNU make version + +# Toolchain +CC := gcc +AS := as +LD := ld +AR := ar + +# Paths, including trailing path separator +SOURCEPREFIX := ./ +BUILDPREFIX := build/ + +# This example needs the mesh lib +MESH_LIB_FOLDER := ../lib/ +MESH_LIB := $(MESH_LIB_FOLDER)build/mesh_api_lib.a + +# General compiler flags +CFLAGS := -std=gnu99 -Wall -Werror + +# Targets definition +MAIN_APP := meshAPIExample + +TARGET_APP := $(BUILDPREFIX)$(MAIN_APP) + +# Add Api header +CFLAGS += -I$(MESH_LIB_FOLDER)api +# Add pthtread lib as needed by Mesh Lib +LDFLAGS += -pthread +# Add Reentrant flag as using pthread +CFLAGS += -D_REENTRANT + +# Specific sources for main +SOURCES:= $(SOURCEPREFIX)main.c + +OBJECTS := $(patsubst $(SOURCEPREFIX)%, \ + $(BUILDPREFIX)%, \ + $(SOURCES:.c=.o)) + +# Functions + +# Also create the target directory if it does not exist +define COMPILE + echo " CC $(2)" + mkdir -p $(dir $(1)) + $(CC) $(CFLAGS) -c -o $(1) $(2) +endef + +define LINK + echo " Linking $(1)" + $(CC) $(CFLAGS) $(LDFLAGS) -o $(1) $(2) $(MESH_LIB) +endef + +define CLEAN + echo " Cleaning up" + $(RM) -r $(BUILDPREFIX) +endef + +# Target rules + +# Use dependency files automatically generated by GCC. +# First collect all C source files +AUTODEPS := $(patsubst $(SOURCEPREFIX)%.c, $(BUILDPREFIX)%.d, $(SOURCES)) + +ifeq ($(V),1) +# "V=1" on command line, print commands. +else +# Default, do not print commands. +.SILENT: +endif + +.PHONY: all +all: app + +app: $(TARGET_APP) + +.PHONY: clean +clean: + $(call CLEAN) + +$(MESH_LIB): + make -C $(MESH_LIB_FOLDER) + +$(BUILDPREFIX)%.o: $(SOURCEPREFIX)%.c + $(call COMPILE,$@,$<) + +$(BUILDPREFIX)$(MAIN_APP): $(OBJECTS) $(MESH_LIB) + $(call LINK,$@,$^) diff --git a/example/makefile b/example/makefile index fc5b2ba..15ab268 100644 --- a/example/makefile +++ b/example/makefile @@ -1,87 +1,43 @@ -# Makefile for Wirepas C Mesh API example - -# Toolchain -CC := gcc -AS := as -LD := ld -AR := ar - -# Paths, including trailing path separator -SOURCEPREFIX := ./ -BUILDPREFIX := build/ - -# This example needs the mesh lib -MESH_LIB_FOLDER := ../lib/ -MESH_LIB := $(MESH_LIB_FOLDER)build/mesh_api_lib.a - -# General compiler flags -CFLAGS := -std=gnu99 -Wall -Werror - -# Targets definition -MAIN_APP := meshAPIExample - -TARGET_APP := $(BUILDPREFIX)$(MAIN_APP) - -# Add Api header -CFLAGS += -I$(MESH_LIB_FOLDER)api -# Add pthtread lib as needed by Mesh Lib -LDFLAGS += -pthread -# Add Reentrant flag as using pthread -CFLAGS += -D_REENTRANT - -# Specific sources for main -SOURCES:= $(SOURCEPREFIX)main.c - -OBJECTS := $(patsubst $(SOURCEPREFIX)%, \ - $(BUILDPREFIX)%, \ - $(SOURCES:.c=.o)) - -# Functions - -# Also create the target directory if it does not exist -define COMPILE - echo " CC $(2)" - mkdir -p $(dir $(1)) - $(CC) $(CFLAGS) -c -o $(1) $(2) -endef - -define LINK - echo " Linking $(1)" - $(CC) $(CFLAGS) $(LDFLAGS) -o $(1) $(2) $(MESH_LIB) -endef - -define CLEAN - echo " Cleaning up" - $(RM) -r $(BUILDPREFIX) -endef - -# Target rules - -# Use dependency files automatically generated by GCC. -# First collect all C source files -AUTODEPS := $(patsubst $(SOURCEPREFIX)%.c, $(BUILDPREFIX)%.d, $(SOURCES)) - -ifeq ($(V),1) -# "V=1" on command line, print commands. -else -# Default, do not print commands. -.SILENT: -endif - -.PHONY: all -all: app - -app: $(TARGET_APP) - -.PHONY: clean -clean: - $(call CLEAN) - -$(MESH_LIB): - make -C $(MESH_LIB_FOLDER) - -$(BUILDPREFIX)%.o: $(SOURCEPREFIX)%.c - $(call COMPILE,$@,$<) - -$(BUILDPREFIX)$(MAIN_APP): $(OBJECTS) $(MESH_LIB) - $(call LINK,$@,$^) +# This file selects the correct makefile for Microsoft NMAKE and GNU make + +# Theory of operation: +# +# Microsoft NMAKE considers the caret (^) as an escape character. It is +# possible to specify a literal newline character in a macro by using a +# caret at the end of a line. The next line will then be consumed as part +# of the macro definition. GNU make does not consider a caret as anything +# special, so macro definitions that end in a caret will consume just a +# single line. +# +# This distinction can be used to hide single lines from NMAKE. Putting +# GNU make-specific directives on those lines can then be used to hide +# NMAKE-specific portions from GNU make. + +GNU_MAKE_IF=^ +ifeq (0, 1) # This line only interpreted by GNU make + +# Include NMAKE makefile # # +!INCLUDE nmake.mk # # +# # < This portion only seen by NMAKE # +# Begin skip everything else for NMAKE # # +!IF 0 # # + +GNU_MAKE_ELSE=^ +else # This line only interpreted by GNU make + +# Include GNU make makefile # # +include gnu_make.mk # < This portion only seen by GNU make # +# # # + +GNU_MAKE_ENDIF=^ +endif # This line only interpreted by GNU make + +GNU_MAKE_IF_2=^ +ifeq (0, 1) # This line only interpreted by GNU make + +# End skip everything else for NMAKE # # +!ENDIF # < This portion only seen by NMAKE # +# # # + +GNU_MAKE_ENDIF_2=^ +endif # This line only interpreted by GNU make diff --git a/lib/gnu_make.mk b/lib/gnu_make.mk new file mode 100644 index 0000000..1ff8efc --- /dev/null +++ b/lib/gnu_make.mk @@ -0,0 +1,84 @@ +# Makefile for Wirepas C Mesh API library, GNU make version + +# Toolchain +CC := gcc +AS := as +LD := ld +AR := ar + +# Paths, including trailing path separator +SOURCEPREFIX := +BUILDPREFIX := build/ + +# General compiler flags +CFLAGS := -std=gnu99 -Wall -Werror +# Uncomment the following line only if running with an old stack +#CFLAGS += -DLEGACY_APP_CONFIG + +# Targets definition +LIB_NAME := mesh_api_lib.a + +TARGET_LIB := $(BUILDPREFIX)$(LIB_NAME) + +SOURCES := + +# Add Api header (including logger) +CFLAGS += -Iapi/ + +# Include platform module sources +include platform/gnu_make.mk + +# Include WPC generic sources +include wpc/gnu_make.mk + +OBJECTS := $(patsubst $(SOURCEPREFIX)%, \ + $(BUILDPREFIX)%, \ + $(SOURCES:.c=.o)) + +# Functions + +# Use GCC to automatically generate dependency files for C files. +# Also create the target directory if it does not exist +define COMPILE + echo " CC $(2)" + mkdir -p $(dir $(1)) + $(CC) $(CFLAGS) -c -o $(1) $(2) +endef + +define LINK_LIB + echo " Linking $(1)" + $(AR) rc -o $(1) $(2) +endef + +define CLEAN + echo " Cleaning up" + $(RM) -r $(BUILDPREFIX) +endef + +# Target rules + +# Use dependency files automatically generated by GCC. +# First collect all C source files +AUTODEPS := $(patsubst $(SOURCEPREFIX)%.c, $(BUILDPREFIX)%.d, $(SOURCES)) + +ifeq ($(V),1) +# "V=1" on command line, print commands. +else +# Default, do not print commands. +.SILENT: +endif + +.PHONY: all +all: lib + +lib: $(TARGET_LIB) + +.PHONY: clean +clean: + $(call CLEAN) + +$(BUILDPREFIX)%.o: $(SOURCEPREFIX)%.c + $(call COMPILE,$@,$<) + +$(TARGET_LIB): $(OBJECTS) + $(call LINK_LIB,$@,$^) diff --git a/lib/makefile b/lib/makefile index 0eb90ad..15ab268 100644 --- a/lib/makefile +++ b/lib/makefile @@ -1,84 +1,43 @@ -# Makefile for Wirepas C Mesh API Lib - -# Toolchain -CC := gcc -AS := as -LD := ld -AR := ar - -# Paths, including trailing path separator -SOURCEPREFIX := -BUILDPREFIX := build/ - -# General compiler flags -CFLAGS := -std=gnu99 -Wall -Werror -# Uncomment the following line only if running with an old stack -#CFLAGS += -DLEGACY_APP_CONFIG - -# Targets definition -LIB_NAME := mesh_api_lib.a - -TARGET_LIB := $(BUILDPREFIX)$(LIB_NAME) - -SOURCES := - -# Add Api header (including logger) -CFLAGS += -Iapi/ - -# Include platform module sources -include platform/makefile - -# Include WPC generic sources -include wpc/makefile - -OBJECTS := $(patsubst $(SOURCEPREFIX)%, \ - $(BUILDPREFIX)%, \ - $(SOURCES:.c=.o)) - -# Functions - -# Use GCC to automatically generate dependency files for C files. -# Also create the target directory if it does not exist -define COMPILE - echo " CC $(2)" - mkdir -p $(dir $(1)) - $(CC) $(CFLAGS) -c -o $(1) $(2) -endef - -define LINK_LIB - echo " Linking $(1)" - $(AR) rc -o $(1) $(2) -endef - -define CLEAN - echo " Cleaning up" - $(RM) -r $(BUILDPREFIX) -endef - -# Target rules - -# Use dependency files automatically generated by GCC. -# First collect all C source files -AUTODEPS := $(patsubst $(SOURCEPREFIX)%.c, $(BUILDPREFIX)%.d, $(SOURCES)) - -ifeq ($(V),1) -# "V=1" on command line, print commands. -else -# Default, do not print commands. -.SILENT: -endif - -.PHONY: all -all: lib - -lib: $(TARGET_LIB) - -.PHONY: clean -clean: - $(call CLEAN) - -$(BUILDPREFIX)%.o: $(SOURCEPREFIX)%.c - $(call COMPILE,$@,$<) - -$(TARGET_LIB): $(OBJECTS) - $(call LINK_LIB,$@,$^) +# This file selects the correct makefile for Microsoft NMAKE and GNU make + +# Theory of operation: +# +# Microsoft NMAKE considers the caret (^) as an escape character. It is +# possible to specify a literal newline character in a macro by using a +# caret at the end of a line. The next line will then be consumed as part +# of the macro definition. GNU make does not consider a caret as anything +# special, so macro definitions that end in a caret will consume just a +# single line. +# +# This distinction can be used to hide single lines from NMAKE. Putting +# GNU make-specific directives on those lines can then be used to hide +# NMAKE-specific portions from GNU make. + +GNU_MAKE_IF=^ +ifeq (0, 1) # This line only interpreted by GNU make + +# Include NMAKE makefile # # +!INCLUDE nmake.mk # # +# # < This portion only seen by NMAKE # +# Begin skip everything else for NMAKE # # +!IF 0 # # + +GNU_MAKE_ELSE=^ +else # This line only interpreted by GNU make + +# Include GNU make makefile # # +include gnu_make.mk # < This portion only seen by GNU make # +# # # + +GNU_MAKE_ENDIF=^ +endif # This line only interpreted by GNU make + +GNU_MAKE_IF_2=^ +ifeq (0, 1) # This line only interpreted by GNU make + +# End skip everything else for NMAKE # # +!ENDIF # < This portion only seen by NMAKE # +# # # + +GNU_MAKE_ENDIF_2=^ +endif # This line only interpreted by GNU make diff --git a/lib/nmake.mk b/lib/nmake.mk new file mode 100644 index 0000000..4640904 --- /dev/null +++ b/lib/nmake.mk @@ -0,0 +1 @@ +# TODO diff --git a/lib/platform/makefile b/lib/platform/gnu_make.mk similarity index 100% rename from lib/platform/makefile rename to lib/platform/gnu_make.mk diff --git a/lib/platform/nmake.mk b/lib/platform/nmake.mk new file mode 100644 index 0000000..4640904 --- /dev/null +++ b/lib/platform/nmake.mk @@ -0,0 +1 @@ +# TODO diff --git a/lib/wpc/makefile b/lib/wpc/gnu_make.mk similarity index 89% rename from lib/wpc/makefile rename to lib/wpc/gnu_make.mk index 064c7ab..d7831f3 100644 --- a/lib/wpc/makefile +++ b/lib/wpc/gnu_make.mk @@ -9,4 +9,4 @@ SOURCES += $(WPC_MODULE)msap.c SOURCES += $(WPC_MODULE)csap.c SOURCES += $(WPC_MODULE)attribute.c -CFLAGS += -I$(WPC_MODULE)include/ \ No newline at end of file +CFLAGS += -I$(WPC_MODULE)include/ diff --git a/lib/wpc/nmake.mk b/lib/wpc/nmake.mk new file mode 100644 index 0000000..4640904 --- /dev/null +++ b/lib/wpc/nmake.mk @@ -0,0 +1 @@ +# TODO diff --git a/test/gnu_make.mk b/test/gnu_make.mk new file mode 100644 index 0000000..3f4bead --- /dev/null +++ b/test/gnu_make.mk @@ -0,0 +1,94 @@ +# Makefile for Wirepas C Mesh API test suite, GNU make version + +# Toolchain +CC := gcc +AS := as +LD := ld +AR := ar + +# Paths, including trailing path separator +SOURCEPREFIX := ./ +BUILDPREFIX := build/ + +# This test suite needs the mesh lib +MESH_LIB_FOLDER := ../lib/ +MESH_LIB := $(MESH_LIB_FOLDER)build/mesh_api_lib.a + +# General compiler flags +CFLAGS := -std=gnu99 -Wall -Werror + +# Targets definition +MAIN_APP := meshAPItest + +TARGET_APP := $(BUILDPREFIX)$(MAIN_APP) + +# Add Api header +CFLAGS += -I$(MESH_LIB_FOLDER)api +# Add pthtread lib as needed by Mesh Lib +LDFLAGS += -pthread +# Add Reentrant flag as using pthread +CFLAGS += -D_REENTRANT + +# Test app needs some platform abstraction (It is a hack as not really part of lib API) +CFLAGS += -I$(MESH_LIB_FOLDER)platform + +# Main app +SOURCES := $(SOURCEPREFIX)test_app.c + +# Test cases +CFLAGS += -I$(SOURCEPREFIX) +SOURCES += $(SOURCEPREFIX)test.c + +OBJECTS := $(patsubst $(SOURCEPREFIX)%, \ + $(BUILDPREFIX)%, \ + $(SOURCES:.c=.o)) + +# Functions + +# Also create the target directory if it does not exist +define COMPILE + echo " CC $(2)" + mkdir -p $(dir $(1)) + $(CC) $(CFLAGS) -c -o $(1) $(2) +endef + +define LINK + echo " Linking $(1)" + $(CC) $(CFLAGS) $(LDFLAGS) -o $(1) $(2) $(MESH_LIB) +endef + +define CLEAN + echo " Cleaning up" + $(RM) -r $(BUILDPREFIX) +endef + +# Target rules + +# Use dependency files automatically generated by GCC. +# First collect all C source files +AUTODEPS := $(patsubst $(SOURCEPREFIX)%.c, $(BUILDPREFIX)%.d, $(SOURCES)) + +ifeq ($(V),1) +# "V=1" on command line, print commands. +else +# Default, do not print commands. +.SILENT: +endif + +.PHONY: all +all: app + +app: $(TARGET_APP) + +.PHONY: clean +clean: + $(call CLEAN) + +$(MESH_LIB): + make -C $(MESH_LIB_FOLDER) + +$(BUILDPREFIX)%.o: $(SOURCEPREFIX)%.c + $(call COMPILE,$@,$<) + +$(BUILDPREFIX)$(MAIN_APP): $(OBJECTS) $(MESH_LIB) + $(call LINK,$@,$^) diff --git a/test/makefile b/test/makefile index 3c10bca..15ab268 100644 --- a/test/makefile +++ b/test/makefile @@ -1,94 +1,43 @@ -# Makefile for Wirepas C Mesh API test suite - -# Toolchain -CC := gcc -AS := as -LD := ld -AR := ar - -# Paths, including trailing path separator -SOURCEPREFIX := ./ -BUILDPREFIX := build/ - -# This test suite needs the mesh lib -MESH_LIB_FOLDER := ../lib/ -MESH_LIB := $(MESH_LIB_FOLDER)build/mesh_api_lib.a - -# General compiler flags -CFLAGS := -std=gnu99 -Wall -Werror - -# Targets definition -MAIN_APP := meshAPItest - -TARGET_APP := $(BUILDPREFIX)$(MAIN_APP) - -# Add Api header -CFLAGS += -I$(MESH_LIB_FOLDER)api -# Add pthtread lib as needed by Mesh Lib -LDFLAGS += -pthread -# Add Reentrant flag as using pthread -CFLAGS += -D_REENTRANT - -# Test app needs some platform abstraction (It is a hack as not really part of lib API) -CFLAGS += -I$(MESH_LIB_FOLDER)platform - -# Main app -SOURCES := $(SOURCEPREFIX)test_app.c - -# Test cases -CFLAGS += -I$(SOURCEPREFIX) -SOURCES += $(SOURCEPREFIX)test.c - -OBJECTS := $(patsubst $(SOURCEPREFIX)%, \ - $(BUILDPREFIX)%, \ - $(SOURCES:.c=.o)) - -# Functions - -# Also create the target directory if it does not exist -define COMPILE - echo " CC $(2)" - mkdir -p $(dir $(1)) - $(CC) $(CFLAGS) -c -o $(1) $(2) -endef - -define LINK - echo " Linking $(1)" - $(CC) $(CFLAGS) $(LDFLAGS) -o $(1) $(2) $(MESH_LIB) -endef - -define CLEAN - echo " Cleaning up" - $(RM) -r $(BUILDPREFIX) -endef - -# Target rules - -# Use dependency files automatically generated by GCC. -# First collect all C source files -AUTODEPS := $(patsubst $(SOURCEPREFIX)%.c, $(BUILDPREFIX)%.d, $(SOURCES)) - -ifeq ($(V),1) -# "V=1" on command line, print commands. -else -# Default, do not print commands. -.SILENT: -endif - -.PHONY: all -all: app - -app: $(TARGET_APP) - -.PHONY: clean -clean: - $(call CLEAN) - -$(MESH_LIB): - make -C $(MESH_LIB_FOLDER) - -$(BUILDPREFIX)%.o: $(SOURCEPREFIX)%.c - $(call COMPILE,$@,$<) - -$(BUILDPREFIX)$(MAIN_APP): $(OBJECTS) $(MESH_LIB) - $(call LINK,$@,$^) +# This file selects the correct makefile for Microsoft NMAKE and GNU make + +# Theory of operation: +# +# Microsoft NMAKE considers the caret (^) as an escape character. It is +# possible to specify a literal newline character in a macro by using a +# caret at the end of a line. The next line will then be consumed as part +# of the macro definition. GNU make does not consider a caret as anything +# special, so macro definitions that end in a caret will consume just a +# single line. +# +# This distinction can be used to hide single lines from NMAKE. Putting +# GNU make-specific directives on those lines can then be used to hide +# NMAKE-specific portions from GNU make. + +GNU_MAKE_IF=^ +ifeq (0, 1) # This line only interpreted by GNU make + +# Include NMAKE makefile # # +!INCLUDE nmake.mk # # +# # < This portion only seen by NMAKE # +# Begin skip everything else for NMAKE # # +!IF 0 # # + +GNU_MAKE_ELSE=^ +else # This line only interpreted by GNU make + +# Include GNU make makefile # # +include gnu_make.mk # < This portion only seen by GNU make # +# # # + +GNU_MAKE_ENDIF=^ +endif # This line only interpreted by GNU make + +GNU_MAKE_IF_2=^ +ifeq (0, 1) # This line only interpreted by GNU make + +# End skip everything else for NMAKE # # +!ENDIF # < This portion only seen by NMAKE # +# # # + +GNU_MAKE_ENDIF_2=^ +endif # This line only interpreted by GNU make From 2907f6df2b8d9852c55027e8d345882d5d6984b2 Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Sun, 12 Jan 2020 01:54:43 -0500 Subject: [PATCH 02/21] Add support for Darwin / macOS This commit refactors the platform-specific code and splits it in POSIX, Linux and Darwin (macOS) parts. Both Linux and Darwin use the POSIX functionality, requiring just a small amount of OS-dependent code. Build support with Clang etc. on macOS is also implemented. The build platform is auto-detected by the GNU make makefile. --- example/gnu_make.mk | 43 +++++--------- lib/gnu_make.mk | 32 ++++------ lib/platform.mk | 54 +++++++++++++++++ lib/platform/darwin/serial_darwin.c | 38 ++++++++++++ lib/platform/gnu_make.mk | 24 +++++--- lib/platform/linux/serial_linux.c | 59 +++++++++++++++++++ lib/platform/linux/serial_termios2.c | 41 ------------- lib/platform/linux/serial_termios2.h | 13 ---- lib/platform/{linux => posix}/logger.c | 0 lib/platform/{linux => posix}/platform.c | 0 .../{linux/serial.c => posix/serial_posix.c} | 47 +++++---------- lib/platform/posix/serial_posix.h | 17 ++++++ test/gnu_make.mk | 48 ++++++--------- 13 files changed, 246 insertions(+), 170 deletions(-) create mode 100644 lib/platform.mk create mode 100644 lib/platform/darwin/serial_darwin.c create mode 100644 lib/platform/linux/serial_linux.c delete mode 100644 lib/platform/linux/serial_termios2.c delete mode 100644 lib/platform/linux/serial_termios2.h rename lib/platform/{linux => posix}/logger.c (100%) rename lib/platform/{linux => posix}/platform.c (100%) rename lib/platform/{linux/serial.c => posix/serial_posix.c} (78%) create mode 100644 lib/platform/posix/serial_posix.h diff --git a/example/gnu_make.mk b/example/gnu_make.mk index 924d13a..b7b6812 100644 --- a/example/gnu_make.mk +++ b/example/gnu_make.mk @@ -1,40 +1,32 @@ # Makefile for Wirepas C Mesh API example, GNU make version -# Toolchain -CC := gcc -AS := as -LD := ld -AR := ar +# This example needs the C Mesh API library +MESH_LIB_FOLDER := ../lib/ +MESH_LIB := $(MESH_LIB_FOLDER)build/mesh_api_lib.a + +# Detect platform and set toolchain variables +include $(MESH_LIB_FOLDER)platform.mk # Paths, including trailing path separator SOURCEPREFIX := ./ BUILDPREFIX := build/ -# This example needs the mesh lib -MESH_LIB_FOLDER := ../lib/ -MESH_LIB := $(MESH_LIB_FOLDER)build/mesh_api_lib.a - -# General compiler flags -CFLAGS := -std=gnu99 -Wall -Werror - # Targets definition MAIN_APP := meshAPIExample TARGET_APP := $(BUILDPREFIX)$(MAIN_APP) -# Add Api header +# Add API header CFLAGS += -I$(MESH_LIB_FOLDER)api -# Add pthtread lib as needed by Mesh Lib -LDFLAGS += -pthread -# Add Reentrant flag as using pthread -CFLAGS += -D_REENTRANT -# Specific sources for main +# Source files SOURCES:= $(SOURCEPREFIX)main.c -OBJECTS := $(patsubst $(SOURCEPREFIX)%, \ - $(BUILDPREFIX)%, \ - $(SOURCES:.c=.o)) +# Object files +OBJECTS := $(patsubst $(SOURCEPREFIX)%, \ + $(BUILDPREFIX)%, \ + $(SOURCES:.c=.o)) + # Functions @@ -55,17 +47,14 @@ define CLEAN $(RM) -r $(BUILDPREFIX) endef -# Target rules -# Use dependency files automatically generated by GCC. -# First collect all C source files -AUTODEPS := $(patsubst $(SOURCEPREFIX)%.c, $(BUILDPREFIX)%.d, $(SOURCES)) +# Target rules ifeq ($(V),1) -# "V=1" on command line, print commands. + # "V=1" on command line, print commands else -# Default, do not print commands. .SILENT: + # Default, do not print commands endif .PHONY: all diff --git a/lib/gnu_make.mk b/lib/gnu_make.mk index 1ff8efc..d1bfc7f 100644 --- a/lib/gnu_make.mk +++ b/lib/gnu_make.mk @@ -1,29 +1,25 @@ # Makefile for Wirepas C Mesh API library, GNU make version -# Toolchain -CC := gcc -AS := as -LD := ld -AR := ar +# Variables + +# Detect platform and set toolchain variables +include platform.mk # Paths, including trailing path separator -SOURCEPREFIX := -BUILDPREFIX := build/ +SOURCEPREFIX := +BUILDPREFIX := build/ -# General compiler flags -CFLAGS := -std=gnu99 -Wall -Werror # Uncomment the following line only if running with an old stack #CFLAGS += -DLEGACY_APP_CONFIG # Targets definition LIB_NAME := mesh_api_lib.a - TARGET_LIB := $(BUILDPREFIX)$(LIB_NAME) SOURCES := -# Add Api header (including logger) -CFLAGS += -Iapi/ +# Add API header (including logger) +CFLAGS += -Iapi/ # Include platform module sources include platform/gnu_make.mk @@ -35,6 +31,7 @@ OBJECTS := $(patsubst $(SOURCEPREFIX)%, \ $(BUILDPREFIX)%, \ $(SOURCES:.c=.o)) + # Functions # Use GCC to automatically generate dependency files for C files. @@ -47,7 +44,7 @@ endef define LINK_LIB echo " Linking $(1)" - $(AR) rc -o $(1) $(2) + $(ARCHIVE) $(1) $(2) endef define CLEAN @@ -55,17 +52,14 @@ define CLEAN $(RM) -r $(BUILDPREFIX) endef -# Target rules -# Use dependency files automatically generated by GCC. -# First collect all C source files -AUTODEPS := $(patsubst $(SOURCEPREFIX)%.c, $(BUILDPREFIX)%.d, $(SOURCES)) +# Target rules ifeq ($(V),1) -# "V=1" on command line, print commands. + # "V=1" on command line, print commands else -# Default, do not print commands. .SILENT: + # Default, do not print commands endif .PHONY: all diff --git a/lib/platform.mk b/lib/platform.mk new file mode 100644 index 0000000..613b2eb --- /dev/null +++ b/lib/platform.mk @@ -0,0 +1,54 @@ +# Build platform detection for Wirepas C Mesh API library, GNU make version + +# Detect platform +ifeq ($(OS),Windows_NT) + $(error GNU make on Windows is not supported. \ + Please build with Visual Studio NMAKE) +else + UNAME := $(shell uname -s) + ifeq ($(UNAME),Linux) + $(info Platform: Linux) + PLATFORM_IS_POSIX := 1 + PLATFORM_IS_LINUX := 1 + CFLAGS += -DPLATFORM_IS_POSIX=1 -DPLATFORM_IS_LINUX=1 + else ifeq ($(UNAME),Darwin) + $(info Platform: Darwin / macOS) + PLATFORM_IS_POSIX := 1 + PLATFORM_IS_DARWIN := 1 + CFLAGS += -DPLATFORM_IS_POSIX=1 -DPLATFORM_IS_DARWIN=1 + else + $(error Platform not recognized) + endif +endif + +# Select toolchain based on platform +ifeq ($(PLATFORM_IS_DARWIN),1) + # Clang toolchain on Darwin / macOS + CC := clang + AS := as + LD := ld + + # Clang compiler flags + CFLAGS += -std=gnu99 -Wall -Werror -pthread + CFLAGS += -Wno-tautological-constant-out-of-range-compare + + # Linker flags + LDFLAGS += + + # A command to turn a list of object files into a static library + ARCHIVE := libtool -static -o +else ifeq ($(PLATFORM_IS_POSIX),1) + # Standard GCC toolchain + CC := gcc + AS := as + LD := ld + + # GCC compiler flags + CFLAGS += -std=gnu99 -Wall -Werror -pthread + + # Linker flags + LDFLAGS += -pthread + + # A command to turn a list of object files into a static library + ARCHIVE := ar rc -o +endif diff --git a/lib/platform/darwin/serial_darwin.c b/lib/platform/darwin/serial_darwin.c new file mode 100644 index 0000000..545d0a8 --- /dev/null +++ b/lib/platform/darwin/serial_darwin.c @@ -0,0 +1,38 @@ +/* Wirepas Oy licensed under Apache License, Version 2.0 + * + * See file LICENSE for full license details. + * + */ + +#include // For ioctl() +#include // For IOSSIOSPEED +#include // For errno + +#include "posix/serial_posix.h" + +#define LOG_MODULE_NAME "SERIAL" +#define MAX_LOG_LEVEL DEBUG_LOG_LEVEL +#include "logger.h" + +int Serial_set_custom_bitrate(int fd, unsigned long bitrate) +{ + // Set custom bitrate on Darwin / macOS + speed_t speed = bitrate; + + if (ioctl(fd, IOSSIOSPEED, &speed) < 0) + { + // Error setting serial port parameters, stop + LOGE("Error %d from IOSSIOSPEED\n", errno); + return -1; + } + + LOGD("Custom bitrate set: %lu\n", bitrate); + + return 0; +} + +int Serial_set_extra_params(int fd) +{ + // Nothing to do + return 0; +} diff --git a/lib/platform/gnu_make.mk b/lib/platform/gnu_make.mk index e12f3c9..fd4da2a 100644 --- a/lib/platform/gnu_make.mk +++ b/lib/platform/gnu_make.mk @@ -1,13 +1,21 @@ # Sources for platform module PLATFORM_MODULE = $(SOURCEPREFIX)platform/ -# For now, only support linux platform -SOURCES += $(PLATFORM_MODULE)linux/platform.c -SOURCES += $(PLATFORM_MODULE)linux/serial.c -SOURCES += $(PLATFORM_MODULE)linux/serial_termios2.c -SOURCES += $(PLATFORM_MODULE)linux/logger.c - -# Add the reentrant flag as using pthread lib -CFLAGS += -D_REENTRANT +ifeq ($(PLATFORM_IS_POSIX),1) + # POSIX modules that support Linux, Darwin (macOS), the various BSDs, ... + SOURCES += $(PLATFORM_MODULE)posix/platform.c + SOURCES += $(PLATFORM_MODULE)posix/serial_posix.c + SOURCES += $(PLATFORM_MODULE)posix/logger.c +endif + +ifeq ($(PLATFORM_IS_LINUX),1) + # Linux-specific modules + SOURCES += $(PLATFORM_MODULE)linux/serial_linux.c +endif + +ifeq ($(PLATFORM_IS_DARWIN),1) + # Darwin-specific modules + SOURCES += $(PLATFORM_MODULE)darwin/serial_darwin.c +endif CFLAGS += -I$(PLATFORM_MODULE) diff --git a/lib/platform/linux/serial_linux.c b/lib/platform/linux/serial_linux.c new file mode 100644 index 0000000..dea575d --- /dev/null +++ b/lib/platform/linux/serial_linux.c @@ -0,0 +1,59 @@ +/* Wirepas Oy licensed under Apache License, Version 2.0 + * + * See file LICENSE for full license details. + * + */ + +#include +#include +#include +#include +#include + +#include "posix/serial_posix.h" + +#define LOG_MODULE_NAME "SERIAL" +#define MAX_LOG_LEVEL DEBUG_LOG_LEVEL +#include "logger.h" + +int Serial_set_custom_bitrate(int fd, unsigned long bitrate) +{ + struct termios2 tty2; + + if (ioctl(fd, TCGETS2, &tty2) < 0) + { + LOGE("Error %d from TCGETS2\n", errno); + return -1; + } + + // set custom bitrate + tty2.c_cflag &= ~CBAUD; + tty2.c_cflag |= BOTHER; + tty2.c_ispeed = bitrate; + tty2.c_ospeed = bitrate; + + if (ioctl(fd, TCSETS2, &tty2) < 0) + { + LOGE("Error %d from TCSETS2\n", errno); + return -1; + } + + LOGD("Custom bitrate set: %lu\n", bitrate); + + return 0; +} + +int Serial_set_extra_params(int fd) +{ + struct serial_struct serial_s; + + // Set low latency flag of serial device. This flag is driver-dependent. + // On FTDI USB adapters it reduces the latency timer to 1 ms from the + // default of 16 ms. See Part III of the FTDI application note + // "AN232B-04 Data Throughput, Latency and Handshaking" for details + ioctl(fd, TIOCGSERIAL, &serial_s); + serial_s.flags |= ASYNC_LOW_LATENCY; + ioctl(fd, TIOCSSERIAL, &serial_s); + + return 0; +} diff --git a/lib/platform/linux/serial_termios2.c b/lib/platform/linux/serial_termios2.c deleted file mode 100644 index 3c06503..0000000 --- a/lib/platform/linux/serial_termios2.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Wirepas Oy licensed under Apache License, Version 2.0 - * - * See file LICENSE for full license details. - * - */ - -#include -#include -#include -#include - -#define LOG_MODULE_NAME "SERIAL" -#define MAX_LOG_LEVEL DEBUG_LOG_LEVEL -#include "logger.h" - -int Serial_set_termios2_bitrate(int fd, unsigned long bitrate) -{ - struct termios2 tty2; - - if (ioctl(fd, TCGETS2, &tty2) < 0) - { - LOGE("Error %d from TCGETS2", errno); - return -1; - } - - // set custom bitrate - tty2.c_cflag &= ~CBAUD; - tty2.c_cflag |= BOTHER; - tty2.c_ispeed = bitrate; - tty2.c_ospeed = bitrate; - - if (ioctl(fd, TCSETS2, &tty2) < 0) - { - LOGE("Error %d from TCSETS2", errno); - return -1; - } - - LOGD("Custom bitrate set: %lu\n", bitrate); - - return 0; -} diff --git a/lib/platform/linux/serial_termios2.h b/lib/platform/linux/serial_termios2.h deleted file mode 100644 index 259edd4..0000000 --- a/lib/platform/linux/serial_termios2.h +++ /dev/null @@ -1,13 +0,0 @@ -/* Wirepas Oy licensed under Apache License, Version 2.0 - * - * See file LICENSE for full license details. - * - */ - -/** - * \file serial_termios2.h - * A function to set a custom bitrate on Linux, using struct termios2. - * This needs to be in its own file due to Linux header file issues. - */ - -int Serial_set_termios2_bitrate(int fd, unsigned long bitrate); diff --git a/lib/platform/linux/logger.c b/lib/platform/posix/logger.c similarity index 100% rename from lib/platform/linux/logger.c rename to lib/platform/posix/logger.c diff --git a/lib/platform/linux/platform.c b/lib/platform/posix/platform.c similarity index 100% rename from lib/platform/linux/platform.c rename to lib/platform/posix/platform.c diff --git a/lib/platform/linux/serial.c b/lib/platform/posix/serial_posix.c similarity index 78% rename from lib/platform/linux/serial.c rename to lib/platform/posix/serial_posix.c index 36639e6..7078501 100644 --- a/lib/platform/linux/serial.c +++ b/lib/platform/posix/serial_posix.c @@ -11,9 +11,8 @@ #include #include #include -#include -#include "serial_termios2.h" +#include "serial_posix.h" #define LOG_MODULE_NAME "SERIAL" #define MAX_LOG_LEVEL INFO_LOG_LEVEL @@ -24,18 +23,18 @@ static int fd = -1; static int set_interface_attribs(int fd, unsigned long bitrate, int parity) { struct termios tty; - struct serial_struct serial_s; memset(&tty, 0, sizeof tty); if (tcgetattr(fd, &tty) != 0) { - LOGE("Error %d from tcgetattr", errno); + LOGE("Error %d from tcgetattr\n", errno); return -1; } - // default to 9600 bps, but use TCSETS2 to set the actual bitrate - // use a bitrate that is not 115200 or 125000 bps here, to make sure - // TCSETS2 actually sets the bitrate + // default to 9600 bps, but use Serial_set_custom_bitrate() to set the + // actual bitrate in a non-POSIX way. Use a bitrate that is not 115200 or + // 125000 bps here, to make sure Serial_set_custom_bitrate() actually sets + // the bitrate cfsetospeed(&tty, B9600); cfsetispeed(&tty, B9600); @@ -67,39 +66,24 @@ static int set_interface_attribs(int fd, unsigned long bitrate, int parity) if (tcsetattr(fd, TCSANOW, &tty) != 0) { - LOGE("Error %d from tcsetattr", errno); + LOGE("Error %d from tcsetattr\n", errno); return -1; } - if (Serial_set_termios2_bitrate(fd, bitrate) != 0) + // Use a non-POSIX way to set a non-standard bitrate. Do this last + // because tcgetattr() / tcsetattr() fails on some platforms (Darwin) + // after a non-standard bitrate is configured + if (Serial_set_custom_bitrate(fd, bitrate) != 0) { return -1; } - // Set low latency flag to serial - ioctl(fd, TIOCGSERIAL, &serial_s); - serial_s.flags |= ASYNC_LOW_LATENCY; - ioctl(fd, TIOCSSERIAL, &serial_s); - - return 0; -} - -static void set_blocking(int fd, int should_block) -{ - struct termios tty; - memset(&tty, 0, sizeof tty); - if (tcgetattr(fd, &tty) != 0) + if (Serial_set_extra_params(fd) != 0) { - LOGE("Error %d from tggetattr", errno); - return; + return -1; } - tty.c_cc[VMIN] = should_block ? 1 : 0; - // No timeout - tty.c_cc[VTIME] = 0; - - if (tcsetattr(fd, TCSANOW, &tty) != 0) - LOGE("Error %d setting term attributes", errno); + return 0; } /****************************************************************************/ @@ -122,9 +106,6 @@ int Serial_open(const char * port_name, unsigned long bitrate) return -1; } - // set no blocking - set_blocking(fd, 0); - LOGD("Serial opened\n"); return 0; } diff --git a/lib/platform/posix/serial_posix.h b/lib/platform/posix/serial_posix.h new file mode 100644 index 0000000..deb3bdc --- /dev/null +++ b/lib/platform/posix/serial_posix.h @@ -0,0 +1,17 @@ +/** + * \brief Set custom serial bitrate + * \param fd + * The file descriptor of serial device + * \param bitrate + * Custom bitrate to set, in bps + * \return 0 if custom bitrate was set, -1 if not + */ +int Serial_set_custom_bitrate(int fd, unsigned long bitrate); + +/** + * \brief Write data from the serial link + * \param fd + * The file descriptor of serial device + * \return 0 if all is well, -1 if not + */ +int Serial_set_extra_params(int fd); diff --git a/test/gnu_make.mk b/test/gnu_make.mk index 3f4bead..a6289b8 100644 --- a/test/gnu_make.mk +++ b/test/gnu_make.mk @@ -1,47 +1,40 @@ # Makefile for Wirepas C Mesh API test suite, GNU make version -# Toolchain -CC := gcc -AS := as -LD := ld -AR := ar +# This example needs the C Mesh API library +MESH_LIB_FOLDER := ../lib/ +MESH_LIB := $(MESH_LIB_FOLDER)build/mesh_api_lib.a + +# Detect platform and set toolchain variables +include $(MESH_LIB_FOLDER)platform.mk # Paths, including trailing path separator SOURCEPREFIX := ./ BUILDPREFIX := build/ -# This test suite needs the mesh lib -MESH_LIB_FOLDER := ../lib/ -MESH_LIB := $(MESH_LIB_FOLDER)build/mesh_api_lib.a - -# General compiler flags -CFLAGS := -std=gnu99 -Wall -Werror - # Targets definition MAIN_APP := meshAPItest TARGET_APP := $(BUILDPREFIX)$(MAIN_APP) -# Add Api header +# Add API header CFLAGS += -I$(MESH_LIB_FOLDER)api -# Add pthtread lib as needed by Mesh Lib -LDFLAGS += -pthread -# Add Reentrant flag as using pthread -CFLAGS += -D_REENTRANT -# Test app needs some platform abstraction (It is a hack as not really part of lib API) +# Test app needs some platform abstraction +# This is a hack and not really part of the C Mesh API library public API CFLAGS += -I$(MESH_LIB_FOLDER)platform -# Main app +# Main app source file SOURCES := $(SOURCEPREFIX)test_app.c -# Test cases +# Test case source files CFLAGS += -I$(SOURCEPREFIX) SOURCES += $(SOURCEPREFIX)test.c -OBJECTS := $(patsubst $(SOURCEPREFIX)%, \ - $(BUILDPREFIX)%, \ - $(SOURCES:.c=.o)) +# Object files +OBJECTS := $(patsubst $(SOURCEPREFIX)%, \ + $(BUILDPREFIX)%, \ + $(SOURCES:.c=.o)) + # Functions @@ -62,17 +55,14 @@ define CLEAN $(RM) -r $(BUILDPREFIX) endef -# Target rules -# Use dependency files automatically generated by GCC. -# First collect all C source files -AUTODEPS := $(patsubst $(SOURCEPREFIX)%.c, $(BUILDPREFIX)%.d, $(SOURCES)) +# Target rules ifeq ($(V),1) -# "V=1" on command line, print commands. + # "V=1" on command line, print commands else -# Default, do not print commands. .SILENT: + # Default, do not print commands endif .PHONY: all From b08d5f80d4f8cb6c31b269b26956a77d30c45cdc Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Sun, 12 Jan 2020 22:11:31 -0500 Subject: [PATCH 03/21] Harmonize path separator usage in makefile variables As outlined in [CONTRIBUTING.md](CONTRIBUTING.md), path variables in makefiles should not have a trailing path separator. This commit fixes that. --- example/gnu_make.mk | 26 +++++++++++++------------- lib/gnu_make.mk | 20 ++++++++++---------- lib/platform/gnu_make.mk | 12 ++++++------ lib/wpc/gnu_make.mk | 18 +++++++++--------- test/gnu_make.mk | 30 +++++++++++++++--------------- 5 files changed, 53 insertions(+), 53 deletions(-) diff --git a/example/gnu_make.mk b/example/gnu_make.mk index b7b6812..df16157 100644 --- a/example/gnu_make.mk +++ b/example/gnu_make.mk @@ -1,30 +1,30 @@ # Makefile for Wirepas C Mesh API example, GNU make version # This example needs the C Mesh API library -MESH_LIB_FOLDER := ../lib/ -MESH_LIB := $(MESH_LIB_FOLDER)build/mesh_api_lib.a +MESH_LIB_FOLDER := ../lib +MESH_LIB := $(MESH_LIB_FOLDER)/build/mesh_api_lib.a # Detect platform and set toolchain variables -include $(MESH_LIB_FOLDER)platform.mk +include $(MESH_LIB_FOLDER)/platform.mk -# Paths, including trailing path separator -SOURCEPREFIX := ./ -BUILDPREFIX := build/ +# Path of source files and build outputs +SOURCEPREFIX := . +BUILDPREFIX := build # Targets definition MAIN_APP := meshAPIExample -TARGET_APP := $(BUILDPREFIX)$(MAIN_APP) +TARGET_APP := $(BUILDPREFIX)/$(MAIN_APP) # Add API header -CFLAGS += -I$(MESH_LIB_FOLDER)api +CFLAGS += -I$(MESH_LIB_FOLDER)/api # Source files -SOURCES:= $(SOURCEPREFIX)main.c +SOURCES:= $(SOURCEPREFIX)/main.c # Object files -OBJECTS := $(patsubst $(SOURCEPREFIX)%, \ - $(BUILDPREFIX)%, \ +OBJECTS := $(patsubst $(SOURCEPREFIX)/%, \ + $(BUILDPREFIX)/%, \ $(SOURCES:.c=.o)) @@ -69,8 +69,8 @@ clean: $(MESH_LIB): make -C $(MESH_LIB_FOLDER) -$(BUILDPREFIX)%.o: $(SOURCEPREFIX)%.c +$(BUILDPREFIX)/%.o: $(SOURCEPREFIX)/%.c $(call COMPILE,$@,$<) -$(BUILDPREFIX)$(MAIN_APP): $(OBJECTS) $(MESH_LIB) +$(BUILDPREFIX)/$(MAIN_APP): $(OBJECTS) $(MESH_LIB) $(call LINK,$@,$^) diff --git a/lib/gnu_make.mk b/lib/gnu_make.mk index d1bfc7f..fb58925 100644 --- a/lib/gnu_make.mk +++ b/lib/gnu_make.mk @@ -5,21 +5,21 @@ # Detect platform and set toolchain variables include platform.mk -# Paths, including trailing path separator -SOURCEPREFIX := -BUILDPREFIX := build/ +# Path of source files and build outputs +SOURCEPREFIX := . +BUILDPREFIX := build # Uncomment the following line only if running with an old stack #CFLAGS += -DLEGACY_APP_CONFIG # Targets definition -LIB_NAME := mesh_api_lib.a -TARGET_LIB := $(BUILDPREFIX)$(LIB_NAME) +LIB_NAME := mesh_api_lib +TARGET_LIB := $(BUILDPREFIX)/$(LIB_NAME).a SOURCES := -# Add API header (including logger) -CFLAGS += -Iapi/ +# Add API header (including logger) and internal headers +CFLAGS += -Iapi -Iinclude # Include platform module sources include platform/gnu_make.mk @@ -27,8 +27,8 @@ include platform/gnu_make.mk # Include WPC generic sources include wpc/gnu_make.mk -OBJECTS := $(patsubst $(SOURCEPREFIX)%, \ - $(BUILDPREFIX)%, \ +OBJECTS := $(patsubst $(SOURCEPREFIX)/%, \ + $(BUILDPREFIX)/%, \ $(SOURCES:.c=.o)) @@ -71,7 +71,7 @@ lib: $(TARGET_LIB) clean: $(call CLEAN) -$(BUILDPREFIX)%.o: $(SOURCEPREFIX)%.c +$(BUILDPREFIX)/%.o: $(SOURCEPREFIX)/%.c $(call COMPILE,$@,$<) $(TARGET_LIB): $(OBJECTS) diff --git a/lib/platform/gnu_make.mk b/lib/platform/gnu_make.mk index fd4da2a..6e3cb16 100644 --- a/lib/platform/gnu_make.mk +++ b/lib/platform/gnu_make.mk @@ -1,21 +1,21 @@ # Sources for platform module -PLATFORM_MODULE = $(SOURCEPREFIX)platform/ +PLATFORM_MODULE = $(SOURCEPREFIX)/platform ifeq ($(PLATFORM_IS_POSIX),1) # POSIX modules that support Linux, Darwin (macOS), the various BSDs, ... - SOURCES += $(PLATFORM_MODULE)posix/platform.c - SOURCES += $(PLATFORM_MODULE)posix/serial_posix.c - SOURCES += $(PLATFORM_MODULE)posix/logger.c + SOURCES += $(PLATFORM_MODULE)/posix/logger.c + SOURCES += $(PLATFORM_MODULE)/posix/platform.c + SOURCES += $(PLATFORM_MODULE)/posix/serial_posix.c endif ifeq ($(PLATFORM_IS_LINUX),1) # Linux-specific modules - SOURCES += $(PLATFORM_MODULE)linux/serial_linux.c + SOURCES += $(PLATFORM_MODULE)/linux/serial_linux.c endif ifeq ($(PLATFORM_IS_DARWIN),1) # Darwin-specific modules - SOURCES += $(PLATFORM_MODULE)darwin/serial_darwin.c + SOURCES += $(PLATFORM_MODULE)/darwin/serial_darwin.c endif CFLAGS += -I$(PLATFORM_MODULE) diff --git a/lib/wpc/gnu_make.mk b/lib/wpc/gnu_make.mk index d7831f3..1789d47 100644 --- a/lib/wpc/gnu_make.mk +++ b/lib/wpc/gnu_make.mk @@ -1,12 +1,12 @@ # Sources for WPC module -WPC_MODULE = $(SOURCEPREFIX)wpc/ +WPC_MODULE = $(SOURCEPREFIX)/wpc -SOURCES += $(WPC_MODULE)wpc.c -SOURCES += $(WPC_MODULE)slip.c -SOURCES += $(WPC_MODULE)wpc_internal.c -SOURCES += $(WPC_MODULE)dsap.c -SOURCES += $(WPC_MODULE)msap.c -SOURCES += $(WPC_MODULE)csap.c -SOURCES += $(WPC_MODULE)attribute.c +SOURCES += $(WPC_MODULE)/wpc.c +SOURCES += $(WPC_MODULE)/slip.c +SOURCES += $(WPC_MODULE)/wpc_internal.c +SOURCES += $(WPC_MODULE)/dsap.c +SOURCES += $(WPC_MODULE)/msap.c +SOURCES += $(WPC_MODULE)/csap.c +SOURCES += $(WPC_MODULE)/attribute.c -CFLAGS += -I$(WPC_MODULE)include/ +CFLAGS += -I$(WPC_MODULE)/include diff --git a/test/gnu_make.mk b/test/gnu_make.mk index a6289b8..839a72c 100644 --- a/test/gnu_make.mk +++ b/test/gnu_make.mk @@ -1,38 +1,38 @@ # Makefile for Wirepas C Mesh API test suite, GNU make version # This example needs the C Mesh API library -MESH_LIB_FOLDER := ../lib/ -MESH_LIB := $(MESH_LIB_FOLDER)build/mesh_api_lib.a +MESH_LIB_FOLDER := ../lib +MESH_LIB := $(MESH_LIB_FOLDER)/build/mesh_api_lib.a # Detect platform and set toolchain variables -include $(MESH_LIB_FOLDER)platform.mk +include $(MESH_LIB_FOLDER)/platform.mk -# Paths, including trailing path separator -SOURCEPREFIX := ./ -BUILDPREFIX := build/ +# Path of source files and build outputs +SOURCEPREFIX := . +BUILDPREFIX := build # Targets definition MAIN_APP := meshAPItest -TARGET_APP := $(BUILDPREFIX)$(MAIN_APP) +TARGET_APP := $(BUILDPREFIX)/$(MAIN_APP) # Add API header -CFLAGS += -I$(MESH_LIB_FOLDER)api +CFLAGS += -I$(MESH_LIB_FOLDER)/api # Test app needs some platform abstraction # This is a hack and not really part of the C Mesh API library public API -CFLAGS += -I$(MESH_LIB_FOLDER)platform +CFLAGS += -I$(MESH_LIB_FOLDER)/platform # Main app source file -SOURCES := $(SOURCEPREFIX)test_app.c +SOURCES := $(SOURCEPREFIX)/test_app.c # Test case source files CFLAGS += -I$(SOURCEPREFIX) -SOURCES += $(SOURCEPREFIX)test.c +SOURCES += $(SOURCEPREFIX)/test.c # Object files -OBJECTS := $(patsubst $(SOURCEPREFIX)%, \ - $(BUILDPREFIX)%, \ +OBJECTS := $(patsubst $(SOURCEPREFIX)/%, \ + $(BUILDPREFIX)/%, \ $(SOURCES:.c=.o)) @@ -77,8 +77,8 @@ clean: $(MESH_LIB): make -C $(MESH_LIB_FOLDER) -$(BUILDPREFIX)%.o: $(SOURCEPREFIX)%.c +$(BUILDPREFIX)/%.o: $(SOURCEPREFIX)/%.c $(call COMPILE,$@,$<) -$(BUILDPREFIX)$(MAIN_APP): $(OBJECTS) $(MESH_LIB) +$(BUILDPREFIX)/$(MAIN_APP): $(OBJECTS) $(MESH_LIB) $(call LINK,$@,$^) From 65ad696baefc9579316f90b0285803c0655ea85a Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Sun, 12 Jan 2020 22:12:21 -0500 Subject: [PATCH 04/21] Add optimization flags Turns out that optimization was not turned on for the C Mesh API library. Added the compiler flags to turn on optimizations. --- lib/platform.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/platform.mk b/lib/platform.mk index 613b2eb..1b64f55 100644 --- a/lib/platform.mk +++ b/lib/platform.mk @@ -29,7 +29,7 @@ ifeq ($(PLATFORM_IS_DARWIN),1) LD := ld # Clang compiler flags - CFLAGS += -std=gnu99 -Wall -Werror -pthread + CFLAGS += -std=gnu99 -Wall -Werror -Os -pthread CFLAGS += -Wno-tautological-constant-out-of-range-compare # Linker flags @@ -44,7 +44,7 @@ else ifeq ($(PLATFORM_IS_POSIX),1) LD := ld # GCC compiler flags - CFLAGS += -std=gnu99 -Wall -Werror -pthread + CFLAGS += -std=gnu99 -Wall -Werror -Os -pthread # Linker flags LDFLAGS += -pthread From 39e2844046af4fcb0244ba583f256eee321e84e0 Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Sun, 12 Jan 2020 22:24:24 -0500 Subject: [PATCH 05/21] Add missing "void" in function prototypes and definitions --- lib/api/wpc.h | 20 ++++++++++---------- lib/platform/platform.h | 10 +++++----- lib/wpc/include/csap.h | 2 +- lib/wpc/include/dsap.h | 2 +- lib/wpc/include/msap.h | 16 ++++++++-------- lib/wpc/wpc.c | 20 ++++++++++---------- 6 files changed, 35 insertions(+), 35 deletions(-) diff --git a/lib/api/wpc.h b/lib/api/wpc.h index db10669..4afaef8 100644 --- a/lib/api/wpc.h +++ b/lib/api/wpc.h @@ -353,7 +353,7 @@ app_res_e WPC_is_cipher_key_set(bool * set_p); * \brief Remove the cipher key * \return Return code of the operation */ -app_res_e WPC_remove_cipher_key(); +app_res_e WPC_remove_cipher_key(void); /** * \brief Set the authentication key @@ -375,7 +375,7 @@ app_res_e WPC_is_authentication_key_set(bool * set_p); * \brief Remove the authentication key * \return Return code of the operation */ -app_res_e WPC_remove_authentication_key(); +app_res_e WPC_remove_authentication_key(void); /** * \brief Get the Firmware version @@ -401,7 +401,7 @@ app_res_e WPC_get_channel_limits(uint8_t * first_channel_p, uint8_t * last_chann * \brief Clear all persistent attributes * \return Return code of the operation */ -app_res_e WPC_do_factory_reset(); +app_res_e WPC_do_factory_reset(void); /** * \brief Get the radio hardware used @@ -532,7 +532,7 @@ app_res_e WPC_register_for_app_config_data(onAppConfigDataReceived_cb_f onAppCon * \brief Unregister for receiving app config data * \return Return code of the operation */ -app_res_e WPC_unregister_from_app_config_data(); +app_res_e WPC_unregister_from_app_config_data(void); /** * \brief Get the stack status @@ -718,14 +718,14 @@ app_res_e WPC_upload_local_scratchpad(uint32_t len, uint8_t * bytes, uint8_t seq * \brief Clear the local stored scratchpad * \return Return code of the operation */ -app_res_e WPC_clear_local_scratchpad(); +app_res_e WPC_clear_local_scratchpad(void); /** * \brief Mark the scratchpad for processing by the bootloader. * The bootloader will process the scratchpad contents on next reboot * \return Return code of the operation */ -app_res_e WPC_update_local_scratchpad(); +app_res_e WPC_update_local_scratchpad(void); /** * \brief Query scratchpad status for a remote node @@ -760,7 +760,7 @@ app_res_e WPC_remote_scratchpad_update(app_addr_t destination_address, * \note Doing a scan consumes quite a lot of power and must be used with * care on battery operated devices */ -app_res_e WPC_start_scan_neighbors(); +app_res_e WPC_start_scan_neighbors(void); /** * \brief Get the list of the current neighbors nodes @@ -894,7 +894,7 @@ app_res_e WPC_register_for_remote_status(onRemoteStatus_cb_f onRemoteStatusRecei * \brief Unregister for receiving remote status packets * \return Return code of the operation */ -app_res_e WPC_unregister_for_remote_status(); +app_res_e WPC_unregister_for_remote_status(void); /** * \brief Callback definition to register for scan neighbors done @@ -918,7 +918,7 @@ app_res_e WPC_register_for_scan_neighbors_done(onScanNeighborsDone_cb_f onScanNe * \brief Unregister from receiving scan neighbors done event * \return Return code of the operation */ -app_res_e WPC_unregister_from_scan_neighbors_done(); +app_res_e WPC_unregister_from_scan_neighbors_done(void); /** * \brief Callback definition to register for stack status event @@ -942,6 +942,6 @@ app_res_e WPC_register_for_stack_status(onStackStatusReceived_cb_f onStackStatus * \brief Unregister from receiving stack status event * \return Return code of the operation */ -app_res_e WPC_unregister_from_stack_status(); +app_res_e WPC_unregister_from_stack_status(void); #endif diff --git a/lib/platform/platform.h b/lib/platform/platform.h index 80cc9ed..dd69cf2 100644 --- a/lib/platform/platform.h +++ b/lib/platform/platform.h @@ -6,7 +6,7 @@ #ifndef PLATFORM_H_ #define PLATFORM_H_ -bool Platform_init(); +bool Platform_init(void); void Platform_usleep(unsigned int time_us); @@ -17,7 +17,7 @@ void Platform_usleep(unsigned int time_us); * to convert it later. * \return Timestamp when the call to this function is made */ -unsigned long long Platform_get_timestamp_ms_epoch(); +unsigned long long Platform_get_timestamp_ms_epoch(void); /** * \brief Call at the beginning of a locked section to send a request @@ -28,13 +28,13 @@ unsigned long long Platform_get_timestamp_ms_epoch(); * from same thread as other API requests, it has to be implemented * accordingly to the architecture chosen. */ -bool Platform_lock_request(); +bool Platform_lock_request(void); /** * * \brief Called at the end of a locked section to send a request */ -void Platform_unlock_request(); +void Platform_unlock_request(void); /** * \brief Set maximum duration the poll requests are accepted to fail @@ -46,6 +46,6 @@ void Platform_unlock_request(); */ bool Platform_set_max_poll_fail_duration(unsigned long duration_s); -void Platform_close(); +void Platform_close(void); #endif /* PLATFORM_H_ */ diff --git a/lib/wpc/include/csap.h b/lib/wpc/include/csap.h index b840347..583ad41 100644 --- a/lib/wpc/include/csap.h +++ b/lib/wpc/include/csap.h @@ -80,6 +80,6 @@ static inline int csap_attribute_read_request(uint16_t attribute_id, * \return negative value if the request fails, * a Mesh positive result otherwise */ -int csap_factory_reset_request(); +int csap_factory_reset_request(void); #endif /* CSAP_H_ */ diff --git a/lib/wpc/include/dsap.h b/lib/wpc/include/dsap.h index e35af2c..480c110 100644 --- a/lib/wpc/include/dsap.h +++ b/lib/wpc/include/dsap.h @@ -143,6 +143,6 @@ bool dsap_unregister_for_data(uint8_t dst_ep); /** * \brief Initialize the dsap module */ -void dsap_init(); +void dsap_init(void); #endif /* DSAP_H_ */ diff --git a/lib/wpc/include/msap.h b/lib/wpc/include/msap.h index d58aebd..63395da 100644 --- a/lib/wpc/include/msap.h +++ b/lib/wpc/include/msap.h @@ -248,7 +248,7 @@ int msap_stack_start_request(uint8_t start_option); * \return negative value if the request fails, * a Mesh positive result otherwise */ -int msap_stack_stop_request(); +int msap_stack_stop_request(void); /** * \brief Request to write data config @@ -312,7 +312,7 @@ int msap_get_nbors_request(msap_get_nbors_conf_pl_t * neigbors_p); * \return negative value if the request fails, * a Mesh positive result otherwise */ -int msap_scan_nbors_request(); +int msap_scan_nbors_request(void); /** * \brief Request to start a scratchpad update @@ -354,14 +354,14 @@ int msap_scratchpad_status_request(msap_scratchpad_status_conf_pl_t * status_p); * \return negative value if the request fails, * a Mesh positive result otherwise */ -int msap_scratchpad_update_request(); +int msap_scratchpad_update_request(void); /** * \brief Clear the stored scratchpad * \return negative value if the request fails, * a Mesh positive result otherwise */ -int msap_scratchpad_clear_request(); +int msap_scratchpad_clear_request(void); /** * \brief Get status of a remote node scratchpad status @@ -442,7 +442,7 @@ bool msap_register_for_app_config(onAppConfigDataReceived_cb_f cb); * \brief Unregister for app config data * \return True if unregistered successfully, false otherwise */ -bool msap_unregister_from_app_config(); +bool msap_unregister_from_app_config(void); /** * \brief Register for remote status @@ -456,7 +456,7 @@ bool msap_register_for_remote_status(onRemoteStatus_cb_f cb); * \brief Unregister from remote status * \return True if unregistered successfully, false otherwise */ -bool msap_unregister_from_remote_status(); +bool msap_unregister_from_remote_status(void); /** * \brief Register for scan neighbors status @@ -470,7 +470,7 @@ bool msap_register_for_scan_neighbors_done(onScanNeighborsDone_cb_f cb); * \brief Unregister from scan neighbors status * \return True if unregistered successfully, false otherwise */ -bool msap_unregister_from_scan_neighbors_done(); +bool msap_unregister_from_scan_neighbors_done(void); /** * \brief Register for stack status @@ -484,6 +484,6 @@ bool msap_register_for_stack_status(onStackStatusReceived_cb_f cb); * \brief Unregister from stack status * \return True if unregistered successfully, false otherwise */ -bool msap_unregister_from_stack_status(); +bool msap_unregister_from_stack_status(void); #endif /* MSAP_H_ */ diff --git a/lib/wpc/wpc.c b/lib/wpc/wpc.c index edfda79..b22475e 100644 --- a/lib/wpc/wpc.c +++ b/lib/wpc/wpc.c @@ -242,7 +242,7 @@ app_res_e WPC_is_cipher_key_set(bool * set_p) return APP_RES_OK; } -app_res_e WPC_remove_cipher_key() +app_res_e WPC_remove_cipher_key(void) { uint8_t disable_key[16]; memset(disable_key, 0xFF, sizeof(disable_key)); @@ -271,7 +271,7 @@ app_res_e WPC_is_authentication_key_set(bool * set_p) return APP_RES_OK; } -app_res_e WPC_remove_authentication_key() +app_res_e WPC_remove_authentication_key(void) { uint8_t disable_key[16]; memset(disable_key, 0xFF, sizeof(disable_key)); @@ -304,7 +304,7 @@ static const app_res_e FACT_RESET_ERROR_CODE_LUT[] = { APP_RES_ACCESS_DENIED // 3 }; -app_res_e WPC_do_factory_reset() +app_res_e WPC_do_factory_reset(void) { int res = csap_factory_reset_request(); @@ -809,7 +809,7 @@ static const app_res_e SCRATCHPAD_CLEAR_LOCAL_ERROR_CODE_LUT[] = { APP_RES_ACCESS_DENIED // 2 }; -app_res_e WPC_clear_local_scratchpad() +app_res_e WPC_clear_local_scratchpad(void) { int res = msap_scratchpad_clear_request(); @@ -824,7 +824,7 @@ static const app_res_e SCRATCHPAD_UPDATE_LOCAL_ERROR_CODE_LUT[] = { APP_RES_ACCESS_DENIED // 3 }; -app_res_e WPC_update_local_scratchpad() +app_res_e WPC_update_local_scratchpad(void) { int res = msap_scratchpad_update_request(); @@ -876,7 +876,7 @@ static const app_res_e SCAN_NEIGHBORS_ERROR_CODE_LUT[] = { APP_RES_ACCESS_DENIED // 2 }; -app_res_e WPC_start_scan_neighbors() +app_res_e WPC_start_scan_neighbors(void) { int res = msap_scan_nbors_request(); @@ -980,7 +980,7 @@ app_res_e WPC_register_for_remote_status(onRemoteStatus_cb_f onRemoteStatusRecei return msap_register_for_remote_status(onRemoteStatusReceived) ? APP_RES_OK : APP_RES_INVALID_VALUE; } -app_res_e WPC_unregister_for_remote_status() +app_res_e WPC_unregister_for_remote_status(void) { return msap_unregister_from_remote_status() ? APP_RES_OK : APP_RES_INVALID_VALUE; } @@ -990,7 +990,7 @@ app_res_e WPC_register_for_app_config_data(onAppConfigDataReceived_cb_f onAppCon return msap_register_for_app_config(onAppConfigDataReceived) ? APP_RES_OK : APP_RES_ALREADY_REGISTERED; } -app_res_e WPC_unregister_from_app_config_data() +app_res_e WPC_unregister_from_app_config_data(void) { return msap_unregister_from_app_config() ? APP_RES_OK : APP_RES_NOT_REGISTERED; } @@ -1000,7 +1000,7 @@ app_res_e WPC_register_for_scan_neighbors_done(onScanNeighborsDone_cb_f onScanNe return msap_register_for_scan_neighbors_done(onScanNeighborDone) ? APP_RES_OK : APP_RES_INVALID_VALUE; } -app_res_e WPC_unregister_from_scan_neighbors_done() +app_res_e WPC_unregister_from_scan_neighbors_done(void) { return msap_unregister_from_scan_neighbors_done() ? APP_RES_OK : APP_RES_INVALID_VALUE; } @@ -1010,7 +1010,7 @@ app_res_e WPC_register_for_stack_status(onStackStatusReceived_cb_f onStackStatus return msap_register_for_stack_status(onStackStatusReceived) ? APP_RES_OK : APP_RES_INVALID_VALUE; } -app_res_e WPC_unregister_from_stack_status() +app_res_e WPC_unregister_from_stack_status(void) { return msap_unregister_from_stack_status() ? APP_RES_OK : APP_RES_INVALID_VALUE; } From 9791a35c179413126b370ddce8b83cae386f123b Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Sun, 12 Jan 2020 23:29:56 -0500 Subject: [PATCH 06/21] Add support for packed structs on Microsoft Visual Studio C compiler The MSVC compiler does not understand the GCC __attribute__ syntax, but uses a __pragma keyword instead. There's a pragma that can be used to enable struct packing for a section of code instead of per type in the type definition, like GCC does. To support both GCC and MSVC in the same source code, an extra header file called "compiler_ext.h" is introduced in this commit. It contains the necessary macro trickery for managing packed structs. --- lib/include/compiler_ext.h | 33 ++++++++++++ lib/wpc/include/attribute.h | 22 +++++--- lib/wpc/include/csap.h | 12 ++++- lib/wpc/include/dsap.h | 32 +++++++---- lib/wpc/include/msap.h | 103 ++++++++++++++++++++++-------------- lib/wpc/include/wpc_types.h | 27 +++++++--- 6 files changed, 164 insertions(+), 65 deletions(-) create mode 100644 lib/include/compiler_ext.h diff --git a/lib/include/compiler_ext.h b/lib/include/compiler_ext.h new file mode 100644 index 0000000..4cca988 --- /dev/null +++ b/lib/include/compiler_ext.h @@ -0,0 +1,33 @@ +// Compiler extensions used by Wirepas C Mesh API + +#ifdef __GNUC__ + +// GNU C compiler extensions + +# define PACKED_STRUCT_START // Not needed + +# define PACKED_STRUCT_END // Not needed + +# define PACKED_STRUCT struct __attribute__((__packed__)) + +#elif defined(_MSC_EXTENSIONS) + +// Microsoft Visual Studio C compiler extensions + +# define PACKED_STRUCT_START __pragma(pack(push, 1)) + +# define PACKED_STRUCT_END __pragma(pack(pop)) + +# define PACKED_STRUCT struct + +#else + +// No compiler extensions supported + +# define PACKED_STRUCT_START + +# define PACKED_STRUCT_END + +# define PACKED_STRUCT struct + +#endif diff --git a/lib/wpc/include/attribute.h b/lib/wpc/include/attribute.h index f599e92..1e90eeb 100644 --- a/lib/wpc/include/attribute.h +++ b/lib/wpc/include/attribute.h @@ -15,26 +15,36 @@ #define ATTRIBUTE_UTIL_H_ #include +#include "compiler_ext.h" -typedef struct __attribute__((__packed__)) +// Start of packed struct definitions +PACKED_STRUCT_START + +typedef PACKED_STRUCT { uint16_t attribute_id; uint8_t attribute_length; uint8_t attribute_value[16]; -} attribute_write_req_pl_t; +} +attribute_write_req_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint16_t attribute_id; -} attribute_read_req_pl_t; +} +attribute_read_req_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint8_t result; uint16_t attribute_id; uint8_t attribute_length; uint8_t attribute_value[16]; -} attribute_read_conf_pl_t; +} +attribute_read_conf_pl_t; + +// End of packed struct definitions +PACKED_STRUCT_END /** * \brief Request to write an attribute to the stack diff --git a/lib/wpc/include/csap.h b/lib/wpc/include/csap.h index 583ad41..83cf2bc 100644 --- a/lib/wpc/include/csap.h +++ b/lib/wpc/include/csap.h @@ -9,6 +9,7 @@ #include #include "wpc_constants.h" #include "attribute.h" +#include "compiler_ext.h" /* Attributes ID */ #define C_NODE_ADDRESS_ID 1 @@ -34,10 +35,17 @@ #define C_FEATURE_LOCK_BITS 22 #define C_FEATURE_LOCK_KEY 23 -typedef struct __attribute__((__packed__)) +// Start of packed struct definitions +PACKED_STRUCT_START + +typedef PACKED_STRUCT { uint32_t reset_key; -} csap_factory_reset_req_pl_t; +} +csap_factory_reset_req_pl_t; + +// End of packed struct definitions +PACKED_STRUCT_END /** * \brief Request to write a configuration attribute to the stack diff --git a/lib/wpc/include/dsap.h b/lib/wpc/include/dsap.h index 480c110..beb3948 100644 --- a/lib/wpc/include/dsap.h +++ b/lib/wpc/include/dsap.h @@ -10,8 +10,12 @@ #include #include "wpc.h" #include "wpc_constants.h" +#include "compiler_ext.h" -typedef struct __attribute__((__packed__)) +// Start of packed struct definitions +PACKED_STRUCT_START + +typedef PACKED_STRUCT { uint16_t pdu_id; uint8_t src_endpoint; @@ -21,9 +25,10 @@ typedef struct __attribute__((__packed__)) uint8_t tx_options; uint8_t apdu_length; uint8_t apdu[MAX_DATA_PDU_SIZE]; -} dsap_data_tx_req_pl_t; +} +dsap_data_tx_req_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint16_t pdu_id; uint8_t src_endpoint; @@ -34,9 +39,10 @@ typedef struct __attribute__((__packed__)) uint32_t buffering_delay; uint8_t apdu_length; uint8_t apdu[MAX_DATA_PDU_SIZE]; -} dsap_data_tx_tt_req_pl_t; +} +dsap_data_tx_tt_req_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint8_t indication_status; uint16_t pdu_id; @@ -45,9 +51,10 @@ typedef struct __attribute__((__packed__)) uint8_t dest_endpoint; uint32_t buffering_delay; uint8_t result; -} dsap_data_tx_ind_pl_t; +} +dsap_data_tx_ind_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint8_t indication_status; uint32_t src_add; @@ -58,14 +65,19 @@ typedef struct __attribute__((__packed__)) uint32_t travel_time; uint8_t apdu_length; uint8_t apdu[MAX_DATA_PDU_SIZE]; -} dsap_data_rx_ind_pl_t; +} +dsap_data_rx_ind_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint16_t pdu_id; uint8_t result; uint8_t capacity; -} dsap_data_tx_conf_pl_t; +} +dsap_data_tx_conf_pl_t; + +// End of packed struct definitions +PACKED_STRUCT_END /** * \brief Function for sending data to the network diff --git a/lib/wpc/include/msap.h b/lib/wpc/include/msap.h index 63395da..b478ce7 100644 --- a/lib/wpc/include/msap.h +++ b/lib/wpc/include/msap.h @@ -12,6 +12,7 @@ #include "wpc_constants.h" #include "attribute.h" #include "util.h" +#include "compiler_ext.h" /* Attributes ID */ #define MSAP_STACK_STATUS 1 @@ -38,57 +39,67 @@ # define MAXIMUM_APP_CONFIG_SIZE 80 #endif // LEGACY_APP_CONFIG -typedef struct __attribute__((__packed__)) +// Start of packed struct definitions +PACKED_STRUCT_START + +typedef PACKED_STRUCT { uint8_t start_option; -} msap_stack_start_req_pl_t; +} +msap_stack_start_req_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint8_t sequence_number; uint16_t diag_data_interval; uint8_t app_config_data[MAXIMUM_APP_CONFIG_SIZE]; -} msap_app_config_data_write_req_pl_t; +} +msap_app_config_data_write_req_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint16_t attribute_id; uint8_t attribute_length; uint8_t attribute_value[16]; -} msap_attribute_write_req_pl_t; +} +msap_attribute_write_req_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint16_t attribute_id; -} msap_attribute_read_req_pl_t; +} +msap_attribute_read_req_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint32_t scratchpad_length; uint8_t scratchpad_sequence_number; -} msap_image_start_req_pl_t; +} +msap_image_start_req_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint32_t start_add; uint8_t number_of_bytes; uint8_t bytes[MAXIMUM_SCRATCHPAD_BLOCK_SIZE]; -} msap_image_block_req_pl_t; +} +msap_image_block_req_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint32_t target; -} msap_image_remote_status_req_pl_t; +} +msap_image_remote_status_req_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint32_t target; uint8_t seq; uint16_t delay_s; +} +msap_image_remote_update_req_pl_t; -} msap_image_remote_update_req_pl_t; - -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint32_t add; uint8_t link_rel; @@ -99,62 +110,71 @@ typedef struct __attribute__((__packed__)) uint8_t tx_power; uint8_t rx_power; uint16_t last_update; -} neighbor_info_t; +} +neighbor_info_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint8_t number_of_neighbors; neighbor_info_t nbors[MAXIMUM_NUMBER_OF_NEIGHBOR]; -} msap_get_nbors_conf_pl_t; +} +msap_get_nbors_conf_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint8_t indication_status; uint8_t scan_ready; -} msap_scan_nbors_ind_pl_t; +} +msap_scan_nbors_ind_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint8_t cost; -} msap_sink_cost_write_req_pl_t; +} +msap_sink_cost_write_req_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint8_t result; uint8_t cost; -} msap_sink_cost_read_conf_pl_t; +} +msap_sink_cost_read_conf_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint8_t indication_status; uint8_t status; -} msap_stack_state_ind_pl_t; +} +msap_stack_state_ind_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint8_t indication_status; uint8_t sequence_number; uint16_t diag_data_interval; uint8_t app_config_data[MAXIMUM_APP_CONFIG_SIZE]; -} msap_app_config_data_rx_ind_pl_t; +} +msap_app_config_data_rx_ind_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint8_t result; uint8_t sequence_number; uint16_t diag_data_interval; uint8_t app_config_data[MAXIMUM_APP_CONFIG_SIZE]; -} msap_app_config_data_read_conf_pl_t; +} +msap_app_config_data_read_conf_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint8_t result; uint16_t attribute_id; uint8_t attribute_length; uint8_t attribute_value[16]; -} msap_attribute_read_conf_pl_t; +} +msap_attribute_read_conf_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint32_t scrat_len; uint16_t scrat_crc; @@ -169,15 +189,20 @@ typedef struct __attribute__((__packed__)) uint8_t firmware_minor_ver; uint8_t firmware_maint_ver; uint8_t firmware_dev_ver; -} msap_scratchpad_status_conf_pl_t; +} +msap_scratchpad_status_conf_pl_t; -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint8_t indication_status; uint32_t source_address; msap_scratchpad_status_conf_pl_t status; uint16_t update_timeout; -} msap_image_remote_status_ind_pl_t; +} +msap_image_remote_status_ind_pl_t; + +// End of packed struct definitions +PACKED_STRUCT_END static inline void convert_internal_to_app_scratchpad_status(app_scratchpad_status_t * status_p, diff --git a/lib/wpc/include/wpc_types.h b/lib/wpc/include/wpc_types.h index 7a1ce33..1df412d 100644 --- a/lib/wpc/include/wpc_types.h +++ b/lib/wpc/include/wpc_types.h @@ -13,32 +13,39 @@ #include "msap.h" #include "attribute.h" #include "wpc_constants.h" +#include "compiler_ext.h" -typedef struct __attribute__((__packed__)) +// Start of packed struct definitions +PACKED_STRUCT_START + +typedef PACKED_STRUCT { uint8_t indication_status; -} generic_ind_pl_t; +} +generic_ind_pl_t; /** * Payload definition for confirm primitives */ -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint8_t result; -} sap_generic_conf_pl_t; +} +sap_generic_conf_pl_t; /** * Payload definition for response primitives */ -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { uint8_t result; -} sap_resp_pl_t; +} +sap_resp_pl_t; /* * Frame type definition */ -typedef struct __attribute__((__packed__)) +typedef PACKED_STRUCT { // Id of the primitive uint8_t primitive_id; @@ -83,7 +90,11 @@ typedef struct __attribute__((__packed__)) // Response sap_resp_pl_t sap_response_payload; } payload; -} wpc_frame_t; +} +wpc_frame_t; + +// End of packed struct definitions +PACKED_STRUCT_END // Size of a given frame #define FRAME_SIZE(__frame_ptr__) ((__frame_ptr__)->payload_length + 3) From f443589dc027b621514fd16527cc32bc362936ca Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Mon, 13 Jan 2020 00:22:27 -0500 Subject: [PATCH 07/21] SLIP module clean-up The internal APIs of the SLIP module had some type inconsistencies and some comments were mangled. This commit cleans up the module and also adds some error checking that was missing. Also, variable length arrays (VLAs) were turned into fixed size arrays, because MSVC does not support VLAs. --- lib/platform/posix/serial_posix.c | 2 +- lib/platform/serial.h | 2 +- lib/wpc/include/slip.h | 58 +++++----- lib/wpc/include/wpc_types.h | 4 - lib/wpc/slip.c | 174 +++++++++++++++--------------- 5 files changed, 119 insertions(+), 121 deletions(-) diff --git a/lib/platform/posix/serial_posix.c b/lib/platform/posix/serial_posix.c index 7078501..67f12dd 100644 --- a/lib/platform/posix/serial_posix.c +++ b/lib/platform/posix/serial_posix.c @@ -179,7 +179,7 @@ int Serial_read(unsigned char * c, unsigned int timeout_ms) } } -int Serial_write(const unsigned char * buffer, unsigned int buffer_size) +int Serial_write(const unsigned char * buffer, size_t buffer_size) { if (fd < 0) { diff --git a/lib/platform/serial.h b/lib/platform/serial.h index 445ef8b..5581ad1 100644 --- a/lib/platform/serial.h +++ b/lib/platform/serial.h @@ -45,4 +45,4 @@ int Serial_read(unsigned char * c, unsigned int timeout_ms); * The size of the buffer to write * \return The number of written char or a negative value in case of error */ -int Serial_write(const unsigned char * buffer, unsigned int buffer_size); +int Serial_write(const unsigned char * buffer, size_t buffer_size); diff --git a/lib/wpc/include/slip.h b/lib/wpc/include/slip.h index 4631832..73d2468 100644 --- a/lib/wpc/include/slip.h +++ b/lib/wpc/include/slip.h @@ -7,21 +7,25 @@ #define SLIP_H__ #include +#include -// Helper macro to correctly size the encoded buffer -#define RECOMMENDED_BUFFER_SIZE(__buffer_in_len__) ((__buffer_in_len__) *2 + 2) +/** + * \brief Maximum number of bytes for \ref Slip_send_buffer() + * and \ref Slip_get_buffer() + */ +#define MAX_SLIP_FRAME_SIZE 256 /** * \brief Decode a slip encoded buffer - * \parambuffer - * buffer address of the encoded buffer. + * \param buffer + * buffer address of the encoded buffer * The same buffer is used to store the decoded buffer - * \paramlen_in + * \param len_in * length of the encoded buffer - * \returnthe length of the decoded buffer or -1 if buffer cannot be decoded + * \return the length of the decoded buffer or < 0 if buffer cannot be decoded * \note This function is public mainly for testing */ -int Slip_decode(uint8_t * buffer, uint32_t len_in); +int Slip_decode(uint8_t * buffer, size_t len_in); /** * \brief Encode a buffer in slip format @@ -32,24 +36,24 @@ int Slip_decode(uint8_t * buffer, uint32_t len_in); * \parambuffer_out * the address to store the encoded buffer * \param len_out - * the length of the provided buffer. - * \returnthe length of the encoded buffer or -1 if the provided + * the length of the provided buffer + * \return the length of the encoded buffer or < 0 if the provided * buffer is too small - * \noteTo be sure that the buffer is big enough, len_out should + * \note To be sure that the buffer is big enough, len_out should * be equal to 2*len_in + 2 * \note This function is public mainly for testing */ -int Slip_encode(uint8_t * buffer_in, uint32_t len_in, uint8_t * buffer_out, uint32_t len_out); +int Slip_encode(const uint8_t * buffer_in, size_t len_in, uint8_t * buffer_out, size_t len_out); /** * \brief Send a buffer in slip encoding * \param buffer * the buffer to send * \param len - * the length of the buffer - * \return 0 for success, -1 otherwise + * length of the buffer to send + * \return 0 for success, < 0 otherwise */ -int Slip_send_buffer(uint8_t * buffer, uint32_t len); +int Slip_send_buffer(const uint8_t * buffer, size_t len); /** * \brief Get a buffer in slip encoding @@ -59,30 +63,30 @@ int Slip_send_buffer(uint8_t * buffer, uint32_t len); * length of the provided buffer * \param timeout_ms * the timeout in millisecond to wait for data - * \return 0 for success, -1 otherwise + * \return 0 for success, < 0 otherwise */ -int Slip_get_buffer(uint8_t * buffer, uint32_t len, uint16_t timeout_ms); +int Slip_get_buffer(uint8_t * buffer, size_t len, unsigned int timeout_ms); /** * \brief Function prototype to write data to serial * \param buffer * the buffer to write * \param buffer_size - * the buffer size to write - * \return the number of bytes written or -1 in case of error + * length of the buffer to write + * \return the number of bytes written or < 0 in case of error */ -typedef int (*write_f)(const unsigned char * buffer, unsigned int buffer_size); +typedef int (*write_f)(const unsigned char * buffer, size_t len); /** - * \brief Function prototype to read single char from serial - * \param c - * the buffer to store read char + * \brief Function prototype to read single byte from serial + * \param byte_p + * the buffer to store read byte * \param timeout_ms - * timeout in ms to receive char - * \return the number of bytes read, 0 in case of timeout or -1 in case of - * error + * timeout in ms to receive byte + * \return the number of bytes read, 0 in case of timeout or < 0 in case of + * error */ -typedef int (*read_f)(unsigned char * c, unsigned int timeout_ms); +typedef int (*read_f)(unsigned char * byte_p, unsigned int timeout_ms); /** * \brief Init function for the slip module @@ -90,7 +94,7 @@ typedef int (*read_f)(unsigned char * c, unsigned int timeout_ms); * A function to write on the serial line * \param read * A function to read on the serial line - * \return 0 in case of success, -1 otherwise + * \return 0 in case of success, < 0 otherwise */ int Slip_init(write_f write, read_f read); diff --git a/lib/wpc/include/wpc_types.h b/lib/wpc/include/wpc_types.h index 1df412d..6fe1bb6 100644 --- a/lib/wpc/include/wpc_types.h +++ b/lib/wpc/include/wpc_types.h @@ -102,10 +102,6 @@ PACKED_STRUCT_END // Max frame size (including crc) #define MAX_FRAME_SIZE (sizeof(wpc_frame_t) + 2) -// Max slip frame size (can be 2 times bigger than a frame if every bytes are -// escaped) -#define MAX_SLIP_FRAME_SIZE (2 * MAX_FRAME_SIZE) - // Define the function type to handle a received frame from the stack (confirm // or indication) typedef int (*frame_handler)(wpc_frame_t * frame); diff --git a/lib/wpc/slip.c b/lib/wpc/slip.c index 97242f7..b61299c 100644 --- a/lib/wpc/slip.c +++ b/lib/wpc/slip.c @@ -58,24 +58,24 @@ static const uint16_t crc_ccitt_lut[] = { #define END_SUBS_OCTET 0xDC #define ESC_SUBS_OCTET 0xDD -// An encoded buffer can be 2 times bigger if all bytes are -// escaped, plus 2 bytes for CRC and 4 bytes for SLIP END symbols -#define MAX_SIZE_ENCODED_BUFFER(__initial_len__) \ - ((__initial_len__ << 1) + 2 + 4) +/** + * \brief Maximum buffer space to reserve for SLIP encoding / decoding + * \note An encoded buffer can be 2 times bigger if all bytes are + * escaped, plus 2 bytes for CRC and 4 bytes for SLIP END symbols + */ +#define MAX_ENCODED_BUFFER_SIZE ((MAX_SLIP_FRAME_SIZE << 1) + 2 + 4) static write_f write_function = NULL; static read_f read_function = NULL; /** - * Compute the crc of a frame + * Compute the CRC of a frame */ -static uint16_t crc_fromBuffer(uint8_t * buf, uint32_t len) +static uint16_t crc_fromBuffer(const uint8_t * buf, size_t len) { uint16_t crc = 0xffff; uint8_t index; - uint32_t i; - - for (i = 0; i < len; i++) + for (size_t i = 0; i < len; i++) { index = buf[i] ^ (crc >> 8); crc = crc_ccitt_lut[index] ^ (crc << 8); @@ -91,11 +91,10 @@ static uint16_t crc_fromBuffer(uint8_t * buf, uint32_t len) * lenght of the escaped frame * \return lenght of the normal frame */ -static uint32_t slip_decode_buffer(uint8_t * buffer, uint32_t len) +static size_t slip_decode_buffer(uint8_t * buffer, size_t len) { - uint8_t write = 0; - uint32_t read; - for (read = 0; read < len; read++) + size_t write = 0; + for (size_t read = 0; read < len; read++) { uint8_t current = buffer[read]; if (current == ESC_SLIP_OCTET) @@ -118,15 +117,13 @@ static uint32_t slip_decode_buffer(uint8_t * buffer, uint32_t len) * buffer of the escaped frame * \param len_buffer * length of the buffer to store the escaped frame - * \return length of the escaped frame or -1 if the escaped frame cannot feet - * the provided buffer + * \return length of the escaped frame or WPC_INT_WRONG_BUFFER_SIZE if the + * escaped frame cannot fit the provided buffer */ -static uint32_t -slip_encode_buffer(uint8_t * buffer, uint32_t len, uint8_t * buffer_escaped, uint32_t len_escaped) +static int slip_encode_buffer(const uint8_t * buffer, size_t len, uint8_t * buffer_escaped, size_t len_escaped) { - uint8_t write = 0; - uint32_t read; - for (read = 0; read < len; read++) + size_t write = 0; + for (size_t read = 0; read < len; read++) { uint8_t current = buffer[read]; if (current == END_SLIP_OCTET || current == ESC_SLIP_OCTET) @@ -143,106 +140,104 @@ slip_encode_buffer(uint8_t * buffer, uint32_t len, uint8_t * buffer_escaped, uin buffer_escaped[write++] = current; } - return write; + return (int) write; } -int Slip_decode(uint8_t * buffer, uint32_t len) +int Slip_decode(uint8_t * buffer, size_t len) { - int decoded_len; - uint16_t crc, crc_from_frame; - - decoded_len = slip_decode_buffer(buffer, len); - /* Compute the crc with SLIP encoding removed */ - crc = crc_fromBuffer(buffer, decoded_len - 2); - /* Get crc from frame */ - crc_from_frame = uint16_decode_le((uint8_t *) (buffer + decoded_len - 2)); - /* Compare crc */ + size_t decoded_len = slip_decode_buffer(buffer, len); + if (decoded_len < 2) + return WPC_INT_WRONG_BUFFER_SIZE; + /* Compute the CRC with SLIP encoding removed */ + uint16_t crc = crc_fromBuffer(buffer, decoded_len - 2); + /* Get CRC from frame */ + uint16_t crc_from_frame = uint16_decode_le(buffer + decoded_len - 2); + /* Compare CRC */ if (crc != crc_from_frame) { LOG_PRINT_BUFFER(buffer, len); - LOGE("Wrong crc 0x%04x (computed) vs 0x%04x (received)\n", crc, crc_from_frame); + LOGE("Wrong CRC 0x%04x (computed) vs 0x%04x (received)\n", crc, crc_from_frame); return WPC_INT_WRONG_CRC; } - return decoded_len - 2; + return (int) (decoded_len - 2); } -int Slip_encode(uint8_t * buffer_in, uint32_t len_in, uint8_t * buffer_out, uint32_t len_out) +int Slip_encode(const uint8_t * buffer_in, size_t len_in, uint8_t * buffer_out, size_t len_out) { - int total_size; - int i; - - // Compute the crc + // Compute the CRC uint16_t crc = crc_fromBuffer(buffer_in, len_in); - // Escape the frame without the crc - total_size = slip_encode_buffer(buffer_in, len_in, buffer_out, len_out); + // Escape the frame without the CRC + size_t total_size = slip_encode_buffer(buffer_in, len_in, buffer_out, len_out); // Check that the buffer is big enough - if (total_size == -1) + if (total_size < 0) { LOGE("Provided buffer in encode is too small\n"); return WPC_INT_WRONG_BUFFER_SIZE; } - // Add the escaped crc to the end of the buffer in LE - i = 0; - while (i < 2) + // Add the escaped CRC to the end of the buffer in little-endian byte order + for (size_t i = 0; i < 2; i++) { uint8_t temp = (crc >> (8 * i)) & 0xff; - int temp_size; - temp_size = slip_encode_buffer(&temp, 1, buffer_out + total_size, len_out - total_size); - if (temp_size == -1) + int temp_size = + slip_encode_buffer(&temp, 1, buffer_out + total_size, len_out - total_size); + if (temp_size < 0) { LOGE("Provided buffer in encode is too small\n"); return WPC_INT_WRONG_BUFFER_SIZE; } - total_size += temp_size; - i++; + total_size += (size_t) temp_size; } - return total_size; + return (int) total_size; } -int Slip_send_buffer(uint8_t * buffer, uint32_t len) +int Slip_send_buffer(const uint8_t * buffer, size_t len) { - int size, written_size; - - // Allocate the encoded buffer. - uint8_t encoded_buffer[MAX_SIZE_ENCODED_BUFFER(len)]; + // Allocate the encoding buffer + uint8_t encoded_buffer[MAX_ENCODED_BUFFER_SIZE]; + size_t encoded_size; // Add 3 end symbols at the beginning - for (int i = 0; i < 3; i++) - encoded_buffer[i] = END_SLIP_OCTET; + for (encoded_size = 0; encoded_size < 3; encoded_size++) + encoded_buffer[encoded_size] = END_SLIP_OCTET; - size = Slip_encode(buffer, len, encoded_buffer + 3, sizeof(encoded_buffer) - 3); + int res = Slip_encode(buffer, len, encoded_buffer + encoded_size, sizeof(encoded_buffer) - 4); + if (res < 0) + { + return res; + } + + encoded_size += (size_t) res; // Add end symbol at the end - encoded_buffer[size + 3] = END_SLIP_OCTET; + encoded_buffer[encoded_size++] = END_SLIP_OCTET; - LOG_PRINT_BUFFER(encoded_buffer, size + 4); + LOG_PRINT_BUFFER(encoded_buffer, encoded_size); - written_size = write_function(encoded_buffer, size + 4); - if (written_size != size + 4) + int written_size = write_function(encoded_buffer, encoded_size); + if ((written_size < 0) || ((size_t) written_size != encoded_size)) { - LOGE("Not able to write all the encoded packet %d vs %d\n", written_size, size + 4); + LOGE("Not able to write all the encoded packet %d vs %d\n", written_size, (int) encoded_size); return WPC_INT_GEN_ERROR; } return 0; } -int Slip_get_buffer(uint8_t * buffer, uint32_t len, uint16_t timeout_ms) +int Slip_get_buffer(uint8_t * buffer, size_t len, unsigned int timeout_ms) { - // Allocate the receiving buffer. - uint8_t receiving_buffer[MAX_SIZE_ENCODED_BUFFER(len)]; - unsigned char read = 0; - int size = 0; - int decoded_size, res; + // Allocate the receiving buffer + uint8_t receiving_buffer[MAX_ENCODED_BUFFER_SIZE]; + size_t size = 0; + int res; bool start_of_frame_detected = false; - // LOGD("In Slip_get_buffer with timeout = %d\n", timeout_s); + // LOGD("In Slip_get_buffer with timeout = %u\n", timeout_ms); while (1) { // Blocking call for timeout_ms @@ -250,20 +245,21 @@ int Slip_get_buffer(uint8_t * buffer, uint32_t len, uint16_t timeout_ms) // should be shortened. But in practice it doesn't really // change anything as once first byte is received, others // are following. - res = read_function(&read, timeout_ms); + unsigned char read_byte = 0; + res = read_function(&read_byte, timeout_ms); if (res == 0) { - LOGW("Timeout to receive frame (size=%d)\n", size); + LOGW("Timeout to receive frame (size=%d)\n", (int) size); return WPC_INT_TIMEOUT_ERROR; } else if (res < 0 || res > 1) { LOGE("Problem in getting buffer res = %d\n", res); } - else if (read == END_SLIP_OCTET) + else if (read_byte == END_SLIP_OCTET) { #ifdef PRINT_RECEIVED_CHAR - LOG_PRINT_BUFFER(&read, 1); + LOG_PRINT_BUFFER(&read_byte, 1); #endif if (start_of_frame_detected) { @@ -274,7 +270,7 @@ int Slip_get_buffer(uint8_t * buffer, uint32_t len, uint16_t timeout_ms) { // It was probably a wrong frame and it is // the start of a frame instead of the end - LOGW("Too small packet received (size=%d)\n", size); + LOGW("Too small packet received (size=%d)\n", (int) size); size = 0; continue; } @@ -283,7 +279,7 @@ int Slip_get_buffer(uint8_t * buffer, uint32_t len, uint16_t timeout_ms) // Id 0x7f is used for internal debugging // It shouldn't be produced in released builds but // discard them anyway - LOGW("Old internal debug print received (size=%d)\n", size); + LOGW("Old internal debug print received (size=%d)\n", (int) size); size = 0; start_of_frame_detected = false; continue; @@ -301,15 +297,14 @@ int Slip_get_buffer(uint8_t * buffer, uint32_t len, uint16_t timeout_ms) #ifdef PRINT_RECEIVED_CHAR LOG_PRINT_BUFFER(&read, 1); #endif - receiving_buffer[size] = read; - size++; - if (size > sizeof(receiving_buffer)) + if (size >= sizeof(receiving_buffer)) { LOGE("Receiving too much bytes from serial line %d vs %d\n", - size, + (int) size, sizeof(receiving_buffer)); return WPC_INT_GEN_ERROR; } + receiving_buffer[size++] = read_byte; } else { @@ -317,16 +312,19 @@ int Slip_get_buffer(uint8_t * buffer, uint32_t len, uint16_t timeout_ms) } } // End of while(1) - // Now, decode the frame - decoded_size = Slip_decode(receiving_buffer, size); - if (decoded_size > 0 && decoded_size <= len) + // Now decode the frame + res = Slip_decode(receiving_buffer, size); + if (res >= 0) { - memcpy(buffer, receiving_buffer, decoded_size); + size_t decoded_size = (size_t) res; + if (decoded_size > 0 && decoded_size <= len) + { + memcpy(buffer, receiving_buffer, decoded_size); + } + LOG_PRINT_BUFFER(buffer, decoded_size); + LOGD("Out of Slip_get_buffer with size = %d\n", (int) decoded_size); } - LOG_PRINT_BUFFER(buffer, decoded_size); - - LOGD("Out of Slip_get_buffer with size = %d\n", decoded_size); - return decoded_size; + return res; } int Slip_init(write_f write, read_f read) From 724da7c7e3552b7cd042466e6f4c1c73e2a3d50c Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Mon, 13 Jan 2020 00:31:38 -0500 Subject: [PATCH 08/21] Turn internal multi-line macros to inline functions for MSVC compatibility Microsoft Visual Studio C compiler does not seem to like the multi-line macros in msap.c and wpc.c. The macros have now been converted to static inline functions. --- lib/wpc/msap.c | 66 ++++++++++++-------------- lib/wpc/wpc.c | 123 ++++++++++++++++++++++++++----------------------- 2 files changed, 95 insertions(+), 94 deletions(-) diff --git a/lib/wpc/msap.c b/lib/wpc/msap.c index 61ebe00..40e8029 100644 --- a/lib/wpc/msap.c +++ b/lib/wpc/msap.c @@ -415,71 +415,65 @@ void msap_scan_nbors_indication_handler(msap_scan_nbors_ind_pl_t * payload) } } -// Macro to avoid code duplication -#define REGISTER_CB(cb, internal_cb) \ - ({ \ - bool res = true; \ - do \ - { \ - Platform_lock_request(); \ - if (internal_cb != NULL) \ - res = false; \ - else \ - internal_cb = cb; \ - Platform_unlock_request(); \ - } while (0); \ - res; \ - }) - -#define UNREGISTER_CB(internal_cb) \ - ({ \ - bool res = true; \ - do \ - { \ - Platform_lock_request(); \ - res = (internal_cb != NULL); \ - internal_cb = NULL; \ - Platform_unlock_request(); \ - } while (0); \ - res; \ - }) +// Inline functions to avoid code duplication +bool register_cb(void * cb, void ** internal_cb) +{ + bool res = true; + Platform_lock_request(); + if (*internal_cb != NULL) + res = false; + else + *internal_cb = cb; + Platform_unlock_request(); + return res; +} + +bool unregister_cb(void ** internal_cb) +{ + bool res = true; + Platform_lock_request(); + res = (internal_cb != NULL); + *internal_cb = NULL; + Platform_unlock_request(); + return res; +} bool msap_register_for_app_config(onAppConfigDataReceived_cb_f cb) { - return REGISTER_CB(cb, m_app_conf_cb); + return register_cb((void *) cb, (void **) &m_app_conf_cb); } bool msap_unregister_from_app_config() { - return UNREGISTER_CB(m_app_conf_cb); + return unregister_cb((void **) &m_app_conf_cb); } bool msap_register_for_remote_status(onRemoteStatus_cb_f cb) { - return REGISTER_CB(cb, m_remote_status_cb); + return register_cb((void *) cb, (void **) &m_remote_status_cb); } bool msap_unregister_from_remote_status() { - return UNREGISTER_CB(m_remote_status_cb); + return unregister_cb((void **) &m_remote_status_cb); } bool msap_register_for_scan_neighbors_done(onScanNeighborsDone_cb_f cb) { - return REGISTER_CB(cb, m_scan_neighbor_cb); + return register_cb((void *) cb, (void **) &m_scan_neighbor_cb); } bool msap_unregister_from_scan_neighbors_done() { - return UNREGISTER_CB(m_scan_neighbor_cb); + return unregister_cb((void **) &m_scan_neighbor_cb); } bool msap_register_for_stack_status(onStackStatusReceived_cb_f cb) { - return REGISTER_CB(cb, m_stack_status_cb); + return register_cb((void *) cb, (void **) &m_stack_status_cb); } bool msap_unregister_from_stack_status() { - return UNREGISTER_CB(m_stack_status_cb); + return unregister_cb((void **) &m_stack_status_cb); } diff --git a/lib/wpc/wpc.c b/lib/wpc/wpc.c index b22475e..4c93322 100644 --- a/lib/wpc/wpc.c +++ b/lib/wpc/wpc.c @@ -16,22 +16,6 @@ #include "wpc_internal.h" #include "platform.h" // For Platform_get_timestamp_ms_epoch() -/** - * \brief Macro to convert dual_mcu return code - * to library error code based on a LUT - * Dual mcu return code are not harmonized so - * a different LUT must be used per fonction - */ -#define convert_error_code(LUT, error) \ - ({ \ - app_res_e ret = APP_RES_INTERNAL_ERROR; \ - if (error >= 0 && error < sizeof(LUT)) \ - { \ - ret = LUT[error]; \ - } \ - ret; \ - }) - /** \brief Timeout to get a valid stack response after * a stop stack. It can be quite long in case of * the bootloader is processing a scratchpad @@ -39,6 +23,29 @@ */ #define TIMEOUT_AFTER_STOP_STACK_S 60 +/** + * \brief An inline function to convert Dual-MCU API return + * code to a C Mesh API library error code + * \note Dual-MCU API return codes are not harmonized, so a + * different look-up table must be used for each function + */ +static inline app_res_e +convert_error_code(const app_res_e * lut, size_t lut_size, unsigned int error) +{ + app_res_e ret = APP_RES_INTERNAL_ERROR; + if (error >= 0 && error < lut_size) + { + ret = lut[error]; + } + return ret; +} + +/** + * \brief Call \ref convert_error_code() with implicit size of array + */ +#define CONVERT_ERROR_CODE(lut, error) \ + convert_error_code(lut, sizeof(lut), error) + app_res_e WPC_initialize(char * port_name, unsigned long bitrate) { return WPC_Int_initialize(port_name, bitrate) == 0 ? APP_RES_OK : APP_RES_INTERNAL_ERROR; @@ -86,14 +93,14 @@ app_res_e WPC_set_max_poll_fail_duration(unsigned long duration_s) app_res_e WPC_get_role(app_role_t * role_p) { int res = csap_attribute_read_request(C_NODE_ROLE_ID, 1, role_p); - return convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); } app_res_e WPC_set_role(app_role_t role) { uint8_t att = role; int res = csap_attribute_write_request(C_NODE_ROLE_ID, 1, &att); - return convert_error_code(ATT_WRITE_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(ATT_WRITE_ERROR_CODE_LUT, res); } app_res_e WPC_get_node_address(app_addr_t * addr_p) @@ -102,7 +109,7 @@ app_res_e WPC_get_node_address(app_addr_t * addr_p) uint8_t att[4]; int res = csap_attribute_read_request(C_NODE_ADDRESS_ID, 4, att); - ret = convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + ret = CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); if (ret != APP_RES_OK) { return ret; @@ -118,7 +125,7 @@ app_res_e WPC_set_node_address(app_addr_t add) uint32_encode_le(add, att); int res = csap_attribute_write_request(C_NODE_ADDRESS_ID, 4, att); - return convert_error_code(ATT_WRITE_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(ATT_WRITE_ERROR_CODE_LUT, res); } app_res_e WPC_get_network_address(net_addr_t * addr_p) @@ -130,7 +137,7 @@ app_res_e WPC_get_network_address(net_addr_t * addr_p) att[3] = 00; int res = csap_attribute_read_request(C_NETWORK_ADDRESS_ID, 3, att); - ret = convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + ret = CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); if (ret != APP_RES_OK) { return ret; @@ -146,14 +153,14 @@ app_res_e WPC_set_network_address(net_addr_t add) uint32_encode_le(add, att); int res = csap_attribute_write_request(C_NETWORK_ADDRESS_ID, 3, att); - return convert_error_code(ATT_WRITE_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(ATT_WRITE_ERROR_CODE_LUT, res); } app_res_e WPC_get_network_channel(net_channel_t * channel_p) { int res = csap_attribute_read_request(C_NETWORK_CHANNEL_ID, 1, channel_p); - return convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); } app_res_e WPC_set_network_channel(net_channel_t channel) @@ -162,25 +169,25 @@ app_res_e WPC_set_network_channel(net_channel_t channel) att = channel; int res = csap_attribute_write_request(C_NETWORK_CHANNEL_ID, 1, &att); - return convert_error_code(ATT_WRITE_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(ATT_WRITE_ERROR_CODE_LUT, res); } app_res_e WPC_get_mtu(uint8_t * value_p) { int res = csap_attribute_read_request(C_MTU_ID, 1, value_p); - return convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); } app_res_e WPC_get_pdu_buffer_size(uint8_t * value_p) { int res = csap_attribute_read_request(C_PDU_BUFFER_SIZE_ID, 1, value_p); - return convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); } app_res_e WPC_get_scratchpad_sequence(uint8_t * value_p) { int res = csap_attribute_read_request(C_SCRATCHPAD_SEQUENCE_ID, 1, value_p); - return convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); } app_res_e WPC_get_mesh_API_version(uint16_t * value_p) @@ -189,7 +196,7 @@ app_res_e WPC_get_mesh_API_version(uint16_t * value_p) uint8_t att[2]; int res = csap_attribute_read_request(C_MESH_API_VER_ID, 2, att); - ret = convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + ret = CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); if (ret != APP_RES_OK) { return ret; @@ -209,7 +216,7 @@ app_res_e WPC_get_firmware_version(uint16_t version[4]) uint8_t att[2]; int res = csap_attribute_read_request(IDs[i], 2, att); - ret = convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + ret = CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); if (ret != APP_RES_OK) { return ret; @@ -225,7 +232,7 @@ app_res_e WPC_set_cipher_key(uint8_t key[16]) { int res = csap_attribute_write_request(C_CIPHER_KEY_ID, 16, key); - return convert_error_code(ATT_WRITE_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(ATT_WRITE_ERROR_CODE_LUT, res); } app_res_e WPC_is_cipher_key_set(bool * set_p) @@ -253,7 +260,7 @@ app_res_e WPC_remove_cipher_key(void) app_res_e WPC_set_authentication_key(uint8_t key[16]) { int res = csap_attribute_write_request(C_AUTH_KEY_ID, 16, key); - return convert_error_code(ATT_WRITE_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(ATT_WRITE_ERROR_CODE_LUT, res); } app_res_e WPC_is_authentication_key_set(bool * set_p) @@ -285,7 +292,7 @@ app_res_e WPC_get_channel_limits(uint8_t * first_channel_p, uint8_t * last_chann uint8_t att[2]; int res = csap_attribute_read_request(C_CHANNEL_LIM_ID, 2, att); - ret = convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + ret = CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); if (ret != APP_RES_OK) { return ret; @@ -308,14 +315,14 @@ app_res_e WPC_do_factory_reset(void) { int res = csap_factory_reset_request(); - return convert_error_code(FACT_RESET_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(FACT_RESET_ERROR_CODE_LUT, res); } app_res_e WPC_get_app_config_data_size(uint8_t * value_p) { int res = csap_attribute_read_request(C_APP_CONFIG_DATA_SIZE_ID, 1, value_p); - return convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); } app_res_e WPC_get_hw_magic(uint16_t * value_p) @@ -324,7 +331,7 @@ app_res_e WPC_get_hw_magic(uint16_t * value_p) uint8_t att[2]; int res = csap_attribute_read_request(C_HW_MAGIC, 2, att); - ret = convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + ret = CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); if (ret != APP_RES_OK) { return ret; @@ -340,7 +347,7 @@ app_res_e WPC_get_stack_profile(uint16_t * value_p) uint8_t att[2]; int res = csap_attribute_read_request(C_STACK_PROFILE, 2, att); - ret = convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + ret = CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); if (ret != APP_RES_OK) { return ret; @@ -356,7 +363,7 @@ app_res_e WPC_get_channel_map(uint32_t * value_p) uint8_t att[4]; int res = csap_attribute_read_request(C_CHANNEL_MAP, 4, att); - ret = convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + ret = CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); if (ret != APP_RES_OK) { return ret; @@ -372,7 +379,7 @@ app_res_e WPC_set_channel_map(uint32_t channel_map) uint32_encode_le(channel_map, att); int res = csap_attribute_write_request(C_CHANNEL_MAP, 4, att); - return convert_error_code(ATT_WRITE_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(ATT_WRITE_ERROR_CODE_LUT, res); } /* Error code LUT for app_config read */ @@ -403,7 +410,7 @@ app_res_e WPC_get_app_config_data(uint8_t * seq_p, uint16_t * interval_p, uint8_ } res = msap_app_config_data_read_request(seq_p, &interval_le, config, size); - ret = convert_error_code(APP_CONFIG_READ_ERROR_CODE_LUT, res); + ret = CONVERT_ERROR_CODE(APP_CONFIG_READ_ERROR_CODE_LUT, res); if (ret != APP_RES_OK) { return ret; @@ -444,7 +451,7 @@ app_res_e WPC_set_app_config_data(uint8_t seq, uint16_t interval, uint8_t * conf res = msap_app_config_data_write_request(seq, interval_le, config, size); - return convert_error_code(APP_CONFIG_WRITE_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(APP_CONFIG_WRITE_ERROR_CODE_LUT, res); } /* Error code LUT for sink cost read/write */ @@ -458,14 +465,14 @@ app_res_e WPC_set_sink_cost(uint8_t cost) { int res = msap_sink_cost_write_request(cost); - return convert_error_code(SINK_COST_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(SINK_COST_ERROR_CODE_LUT, res); } app_res_e WPC_get_sink_cost(uint8_t * cost_p) { int res = msap_sink_cost_read_request(cost_p); - return convert_error_code(SINK_COST_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(SINK_COST_ERROR_CODE_LUT, res); } static bool get_statck_status(uint16_t timeout_s) @@ -569,7 +576,7 @@ static app_res_e read_single_byte_msap(uint8_t att, uint8_t * pointer) // app_res_e ret; res = msap_attribute_read_request(att, 1, pointer); - return convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); } app_res_e WPC_get_stack_status(uint8_t * status_p) @@ -596,7 +603,7 @@ app_res_e WPC_set_remaining_energy(uint8_t energy) { int res = msap_attribute_write_request(MSAP_ENERGY, 1, &energy); - return convert_error_code(ATT_WRITE_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(ATT_WRITE_ERROR_CODE_LUT, res); } app_res_e WPC_get_autostart(uint8_t * enable_p) @@ -608,7 +615,7 @@ app_res_e WPC_set_autostart(uint8_t enable) { int res = msap_attribute_write_request(MSAP_AUTOSTART, 1, &enable); - return convert_error_code(ATT_WRITE_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(ATT_WRITE_ERROR_CODE_LUT, res); } app_res_e WPC_get_route_count(uint8_t * count_p) @@ -623,7 +630,7 @@ app_res_e WPC_get_system_time(uint32_t * time_p) uint32_t internal_time; int res = msap_attribute_read_request(MSAP_SYSTEM_TIME, 4, att); - ret = convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + ret = CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); if (ret != APP_RES_OK) { return ret; @@ -640,7 +647,7 @@ app_res_e WPC_get_access_cycle_range(uint16_t * min_ac_p, uint16_t * max_ac_p) uint8_t att[4]; int res = msap_attribute_read_request(MSAP_ACCESS_CYCLE_RANGE, 4, att); - ret = convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + ret = CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); if (ret != APP_RES_OK) { return ret; @@ -659,7 +666,7 @@ app_res_e WPC_set_access_cycle_range(uint16_t min_ac, uint16_t max_ac) uint16_encode_le(max_ac, att + 2); res = msap_attribute_write_request(MSAP_ACCESS_CYCLE_RANGE, 4, att); - return convert_error_code(ATT_WRITE_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(ATT_WRITE_ERROR_CODE_LUT, res); } app_res_e WPC_get_access_cycle_limits(uint16_t * min_ac_l_p, uint16_t * max_ac_l_p) @@ -668,7 +675,7 @@ app_res_e WPC_get_access_cycle_limits(uint16_t * min_ac_l_p, uint16_t * max_ac_l uint8_t att[4]; int res = msap_attribute_read_request(MSAP_ACCESS_CYCLE_LIMITS, 4, att); - ret = convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + ret = CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); if (ret != APP_RES_OK) { return ret; @@ -685,7 +692,7 @@ app_res_e WPC_get_current_access_cycle(uint16_t * cur_ac_p) uint8_t att[2]; int res = msap_attribute_read_request(MSAP_CURRENT_ACCESS_CYCLE, 2, att); - ret = convert_error_code(ATT_READ_ERROR_CODE_LUT, res); + ret = CONVERT_ERROR_CODE(ATT_READ_ERROR_CODE_LUT, res); if (ret != APP_RES_OK) { return ret; @@ -749,7 +756,7 @@ app_res_e WPC_start_local_scratchpad_update(uint32_t len, uint8_t seq) uint32_encode_le(len, (uint8_t *) &len_le); res = msap_scratchpad_start_request(len_le, seq); - return convert_error_code(SCRATCHPAD_LOCAL_START_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(SCRATCHPAD_LOCAL_START_ERROR_CODE_LUT, res); } /* Error code LUT for local block scratchpad */ @@ -789,7 +796,7 @@ app_res_e WPC_upload_local_block_scratchpad(uint32_t len, uint8_t * bytes, uint3 if (res > 1) { LOGE("Error in loading scratchpad block -> %d\n", res); - return convert_error_code(SCRATCHPAD_LOCAL_BLOCK_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(SCRATCHPAD_LOCAL_BLOCK_ERROR_CODE_LUT, res); } if (res == 1) @@ -813,7 +820,7 @@ app_res_e WPC_clear_local_scratchpad(void) { int res = msap_scratchpad_clear_request(); - return convert_error_code(SCRATCHPAD_CLEAR_LOCAL_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(SCRATCHPAD_CLEAR_LOCAL_ERROR_CODE_LUT, res); } /* Error code LUT for sink cost read/write */ @@ -828,7 +835,7 @@ app_res_e WPC_update_local_scratchpad(void) { int res = msap_scratchpad_update_request(); - return convert_error_code(SCRATCHPAD_UPDATE_LOCAL_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(SCRATCHPAD_UPDATE_LOCAL_ERROR_CODE_LUT, res); } /* Error code LUT for scratchpad remote status */ @@ -844,7 +851,7 @@ app_res_e WPC_get_remote_status(app_addr_t destination_address) uint32_encode_le(destination_address, (uint8_t *) &destination_address_le); int res = msap_scratchpad_remote_status(destination_address_le); - return convert_error_code(SCRATCHPAD_STATUS_REMOTE_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(SCRATCHPAD_STATUS_REMOTE_ERROR_CODE_LUT, res); } /* Error code LUT for scratchpad remote update */ @@ -866,7 +873,7 @@ app_res_e WPC_remote_scratchpad_update(app_addr_t destination_address, uint8_t s uint16_encode_le(reboot_delay_s, (uint8_t *) &reboot_delay_s_le); int res = msap_scratchpad_remote_update(destination_address_le, seq, reboot_delay_s_le); - return convert_error_code(SCRATCHPAD_UPDATE_REMOTE_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(SCRATCHPAD_UPDATE_REMOTE_ERROR_CODE_LUT, res); } /* Error code LUT for scan neighbors */ @@ -880,7 +887,7 @@ app_res_e WPC_start_scan_neighbors(void) { int res = msap_scan_nbors_request(); - return convert_error_code(SCAN_NEIGHBORS_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(SCAN_NEIGHBORS_ERROR_CODE_LUT, res); } app_res_e WPC_get_neighbors(app_nbors_t * nbors_list_p) @@ -934,7 +941,7 @@ app_res_e WPC_send_data_with_options(app_message_t * message_t) message_t->is_unack_csma_ca, message_t->hop_limit); - return convert_error_code(SEND_DATA_ERROR_CODE_LUT, res); + return CONVERT_ERROR_CODE(SEND_DATA_ERROR_CODE_LUT, res); } app_res_e WPC_send_data(const uint8_t * bytes, From b9a6c116612cd8ccd0c538af24104e6ada270644 Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Mon, 13 Jan 2020 00:47:37 -0500 Subject: [PATCH 09/21] Fix miscellaneous compiler warnings from Microsoft Visual Studio C compiler --- lib/wpc/dsap.c | 8 ++++---- lib/wpc/wpc.c | 4 ++-- lib/wpc/wpc_internal.c | 3 +-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/wpc/dsap.c b/lib/wpc/dsap.c index a7e8255..d22bd48 100644 --- a/lib/wpc/dsap.c +++ b/lib/wpc/dsap.c @@ -79,7 +79,7 @@ static void fill_tx_request(wpc_frame_t * request, payload->dest_endpoint = dest_ep; payload->qos = qos; payload->tx_options = tx_options; - payload->apdu_length = len; + payload->apdu_length = (uint8_t) len; // copy the APDU memcpy(&payload->apdu, buffer, len); @@ -104,7 +104,7 @@ static void fill_tx_tt_request(wpc_frame_t * request, payload->dest_endpoint = dest_ep; payload->qos = qos; payload->tx_options = tx_options; - payload->apdu_length = len; + payload->apdu_length = (uint8_t) len; payload->buffering_delay = buffering_delay; // copy the APDU @@ -152,14 +152,14 @@ int dsap_data_tx_request(const uint8_t * buffer, request.primitive_id = DSAP_DATA_TX_REQUEST; fill_tx_request(&request, buffer, len, pdu_id, dest_add, qos, src_ep, dest_ep, tx_options); request.payload_length = - sizeof(dsap_data_tx_req_pl_t) - (MAX_DATA_PDU_SIZE - len); + (uint8_t)(sizeof(dsap_data_tx_req_pl_t) - (MAX_DATA_PDU_SIZE - len)); } else { request.primitive_id = DSAP_DATA_TX_TT_REQUEST; fill_tx_tt_request(&request, buffer, len, pdu_id, dest_add, qos, src_ep, dest_ep, tx_options, buffering_delay); request.payload_length = - sizeof(dsap_data_tx_tt_req_pl_t) - (MAX_DATA_PDU_SIZE - len); + (uint8_t)(sizeof(dsap_data_tx_tt_req_pl_t) - (MAX_DATA_PDU_SIZE - len)); } // Do the sending diff --git a/lib/wpc/wpc.c b/lib/wpc/wpc.c index 4c93322..d869364 100644 --- a/lib/wpc/wpc.c +++ b/lib/wpc/wpc.c @@ -774,7 +774,7 @@ static const app_res_e SCRATCHPAD_LOCAL_BLOCK_ERROR_CODE_LUT[] = { app_res_e WPC_upload_local_block_scratchpad(uint32_t len, uint8_t * bytes, uint32_t start) { app_res_e app_res; - uint8_t res; + int res; uint32_t loaded = 0; uint8_t max_block_size, block_size; @@ -788,7 +788,7 @@ app_res_e WPC_upload_local_block_scratchpad(uint32_t len, uint8_t * bytes, uint3 while (loaded < len) { uint32_t remaining = len - loaded; - block_size = (remaining > max_block_size) ? max_block_size : remaining; + block_size = (remaining > max_block_size) ? max_block_size : (uint8_t) remaining; uint32_t addr_le; uint32_encode_le(start + loaded, (uint8_t *) &addr_le); diff --git a/lib/wpc/wpc_internal.c b/lib/wpc/wpc_internal.c index 1d429e2..48d0b0e 100644 --- a/lib/wpc/wpc_internal.c +++ b/lib/wpc/wpc_internal.c @@ -21,7 +21,6 @@ #include #include -#include // This is the timeout in milliseconds to receive an indication // from stack after a poll request @@ -90,7 +89,7 @@ static int send_response_to_stack(uint8_t primitive_id, uint8_t frame_id, bool m static int send_request_locked(wpc_frame_t * request, wpc_frame_t * confirm, uint16_t timeout_ms) { static uint8_t frame_id = 0; - int confirm_size; + int confirm_size = 0; int attempt = 0; uint8_t buffer[MAX_FRAME_SIZE]; wpc_frame_t * rec_confirm; From fd67bd6b7738fdb9e56c26a1e2e61a1c2733e783 Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Mon, 13 Jan 2020 01:02:48 -0500 Subject: [PATCH 10/21] Fix a bug in setting TX packet callback parameters When a packet is sent, an optional TX callback is called. There was a bug in converting the buffering delay from an internal representation to milliseconds. The TX result (sent / discarded) was also wrong. This commit also fixes some unrelated comment spelling and formatting errors. --- lib/wpc/dsap.c | 4 ++-- lib/wpc/include/msap.h | 7 ++++--- lib/wpc/include/wpc_internal.h | 1 + lib/wpc/wpc.c | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/wpc/dsap.c b/lib/wpc/dsap.c index d22bd48..1cc9d7a 100644 --- a/lib/wpc/dsap.c +++ b/lib/wpc/dsap.c @@ -195,8 +195,8 @@ void dsap_data_tx_indication_handler(dsap_data_tx_ind_pl_t * payload) { LOGD("App cb set, call it...\n"); cb(payload->pdu_id, - payload->buffering_delay, - internal_time_to_ms(payload->indication_status)); + internal_time_to_ms(payload->buffering_delay), + payload->indication_status); } } diff --git a/lib/wpc/include/msap.h b/lib/wpc/include/msap.h index b478ce7..240d9b6 100644 --- a/lib/wpc/include/msap.h +++ b/lib/wpc/include/msap.h @@ -230,9 +230,10 @@ convert_internal_to_app_scratchpad_status(app_scratchpad_status_t * status_p, /** * \brief Convert internal neighbors list returned by get_neighbors to API - * representation \param neighbors_p Pointer to public API neighbor list - * structure \param internal_neighbors_p Pointer to internal msap neighbor - * list structure + * representation + * \param neighbors_p Pointer to public API neighbor list structure + * \param internal_neighbors_p Pointer to internal msap neighbor list + * structure */ static inline void convert_internal_to_app_neighbors_status(app_nbors_t * neighbors_p, diff --git a/lib/wpc/include/wpc_internal.h b/lib/wpc/include/wpc_internal.h index cb22085..bae3a31 100644 --- a/lib/wpc/include/wpc_internal.h +++ b/lib/wpc/include/wpc_internal.h @@ -27,6 +27,7 @@ typedef enum */ typedef void (*onIndicationReceivedLocked_cb_f)(wpc_frame_t * frame, unsigned long long timestamp_ms); + /** * \brief Function to send a request and wait for confirm for default timeout * \param frame diff --git a/lib/wpc/wpc.c b/lib/wpc/wpc.c index d869364..869cd6b 100644 --- a/lib/wpc/wpc.c +++ b/lib/wpc/wpc.c @@ -67,7 +67,7 @@ static const app_res_e ATT_READ_ERROR_CODE_LUT[] = { APP_RES_ACCESS_DENIED // 6 }; -/* Error code LUT for reading attribute */ +/* Error code LUT for writing attribute */ static const app_res_e ATT_WRITE_ERROR_CODE_LUT[] = { APP_RES_OK, // 0 APP_RES_INTERNAL_ERROR, // 1 From 4c306ff12be43c9d2ba6aac553ef1e48cfce22d1 Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Mon, 13 Jan 2020 01:17:57 -0500 Subject: [PATCH 11/21] Add support for building with Microsoft Visual Studio NMAKE This commit adds NMAKE makefiles and a dummy versions of platform-specific functions for Windows. This allows compiling the Wirepas C Mesh API library on Windows, in Visual Studio Developer Command Prompt, by calling NMAKE. Actual implementation of Windows-specific functions will be added in another commit. --- lib/nmake.mk | 73 ++++++++++++++++++++++++++++++- lib/platform/nmake.mk | 10 ++++- lib/platform/win32/logger.c | 24 ++++++++++ lib/platform/win32/platform.c | 53 ++++++++++++++++++++++ lib/platform/win32/serial_win32.c | 37 ++++++++++++++++ lib/wpc/nmake.mk | 13 +++++- 6 files changed, 207 insertions(+), 3 deletions(-) create mode 100644 lib/platform/win32/logger.c create mode 100644 lib/platform/win32/platform.c create mode 100644 lib/platform/win32/serial_win32.c diff --git a/lib/nmake.mk b/lib/nmake.mk index 4640904..0c17b77 100644 --- a/lib/nmake.mk +++ b/lib/nmake.mk @@ -1 +1,72 @@ -# TODO +# Makefile for Wirepas C Mesh API library, Microsoft NMAKE version + +# Variables + +# Microsoft Visual studio command line toolchain on Windows +# Use Visual Studio defaults +#CC = cl +#AS = ml + +# Visual Studio C compiler flags +CFLAGS = $(CFLAGS) /nologo /W4 /WX /O2 /TC + +# Linker flags +LDFLAGS = $(LDFLAGS) + +# Platform flags +!MESSAGE Platform: WIN32 +PLATFORM_IS_WIN32 = 1 +CFLAGS = $(CFLAGS) /DPLATFORM_IS_WIN32=1 + +# Path of source files +SOURCEPREFIX = . + +# Uncomment the following line only if running with an old stack +#CFLAGS += /DLEGACY_APP_CONFIG=1 + +# Targets definition +LIB_NAME = mesh_api_lib +TARGET_LIB = build\$(LIB_NAME).lib + +SOURCES = + +# Add API header (including logger) and internal headers +CFLAGS = $(CFLAGS) /Iapi /Iinclude + +# Include platform module sources +!INCLUDE platform\nmake.mk + +# Include WPC generic sources +!INCLUDE wpc\nmake.mk + +# Object files, one for each C source file +OBJECTS = $(SOURCES:.c=.obj) + + +# Target rules + +!IF "$(V)"=="1" + # "V=1" on command line, print commands +!MESSAGE SOURCES: $(SOURCES) +!MESSAGE OBJECTS: $(OBJECTS) +!ELSE +.SILENT:# Default, do not print commands +!ENDIF + +all: lib + +lib: $(TARGET_LIB) + +clean: + echo Cleaning up + -del $(OBJECTS) >NUL 2>NUL + -rmdir /S /Q $(BUILDPREFIX) >NUL 2>NUL + +.c.obj: + -mkdir $(@D) >NUL 2>NUL + $(CC) $(CFLAGS) /c /Fo$@ $*.c + +$(TARGET_LIB): $(OBJECTS) + echo Linking $@ + -mkdir $(@D) >NUL 2>NUL + lib /NOLOGO /OUT:$@ $** diff --git a/lib/platform/nmake.mk b/lib/platform/nmake.mk index 4640904..7d218bd 100644 --- a/lib/platform/nmake.mk +++ b/lib/platform/nmake.mk @@ -1 +1,9 @@ -# TODO +# Sources for platform module +PLATFORM_MODULE = $(SOURCEPREFIX)\platform + +# Windows-specific modules +SOURCES = $(SOURCES) $(PLATFORM_MODULE)\win32\logger.c +SOURCES = $(SOURCES) $(PLATFORM_MODULE)\win32\platform.c +SOURCES = $(SOURCES) $(PLATFORM_MODULE)\win32\serial_win32.c + +CFLAGS = $(CFLAGS) /I$(PLATFORM_MODULE) diff --git a/lib/platform/win32/logger.c b/lib/platform/win32/logger.c new file mode 100644 index 0000000..2e8bcde --- /dev/null +++ b/lib/platform/win32/logger.c @@ -0,0 +1,24 @@ +/* Wirepas Oy licensed under Apache License, Version 2.0 + * + * See file LICENSE for full license details. + * + */ + +#include +#include + +void Platform_LOG(char level, char * module, char * format, va_list args) +{ + // TODO + (void) level; + (void) module; + (void) format; + (void) args; +} + +void Platform_print_buffer(uint8_t * buffer, int size) +{ + // TODO + (void) buffer; + (void) size; +} diff --git a/lib/platform/win32/platform.c b/lib/platform/win32/platform.c new file mode 100644 index 0000000..8f683ce --- /dev/null +++ b/lib/platform/win32/platform.c @@ -0,0 +1,53 @@ +/* Wirepas Oy licensed under Apache License, Version 2.0 + * + * See file LICENSE for full license details. + * + */ + +#include + +#define LOG_MODULE_NAME "linux_plat" +#define MAX_LOG_LEVEL INFO_LOG_LEVEL +#include "logger.h" +#include "wpc_internal.h" + +void Platform_usleep(unsigned int time_us) +{ + // TODO + (void) time_us; +} + +bool Platform_lock_request(void) +{ + // TODO + return false; +} + +void Platform_unlock_request(void) +{ + // TODO +} + +unsigned long long Platform_get_timestamp_ms_epoch(void) +{ + // TODO + return 0ULL; +} + +bool Platform_init(void) +{ + // TODO + return false; +} + +bool Platform_set_max_poll_fail_duration(unsigned long duration_s) +{ + // TODO + (void) duration_s; + return false; +} + +void Platform_close(void) +{ + // TODO +} diff --git a/lib/platform/win32/serial_win32.c b/lib/platform/win32/serial_win32.c new file mode 100644 index 0000000..3aff22a --- /dev/null +++ b/lib/platform/win32/serial_win32.c @@ -0,0 +1,37 @@ +/* Wirepas Oy licensed under Apache License, Version 2.0 + * + * See file LICENSE for full license details. + * + */ + +#include + +int Serial_open(const char * port_name, unsigned long bitrate) +{ + // TODO + (void) port_name; + (void) bitrate; + return -1; +} + +int Serial_close(void) +{ + // TODO + return -1; +} + +int Serial_read(unsigned char * c, unsigned int timeout_ms) +{ + // TODO + (void) c; + (void) timeout_ms; + return 0; +} + +int Serial_write(const unsigned char * buffer, size_t buffer_size) +{ + // TODO + (void) buffer; + (void) buffer_size; + return 0; +} diff --git a/lib/wpc/nmake.mk b/lib/wpc/nmake.mk index 4640904..99cd560 100644 --- a/lib/wpc/nmake.mk +++ b/lib/wpc/nmake.mk @@ -1 +1,12 @@ -# TODO +# Sources for WPC module +WPC_MODULE = $(SOURCEPREFIX)\wpc + +SOURCES = $(SOURCES) $(WPC_MODULE)\wpc.c +SOURCES = $(SOURCES) $(WPC_MODULE)\slip.c +SOURCES = $(SOURCES) $(WPC_MODULE)\wpc_internal.c +SOURCES = $(SOURCES) $(WPC_MODULE)\dsap.c +SOURCES = $(SOURCES) $(WPC_MODULE)\msap.c +SOURCES = $(SOURCES) $(WPC_MODULE)\csap.c +SOURCES = $(SOURCES) $(WPC_MODULE)\attribute.c + +CFLAGS = $(CFLAGS) /I$(WPC_MODULE)\include From c58cf7e2d49290775a61658120be2d3b9d5113da Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Mon, 13 Jan 2020 01:47:21 -0500 Subject: [PATCH 12/21] Fix problems found by Codacy/PR Quality Review --- lib/wpc/slip.c | 12 ++++++------ lib/wpc/wpc.c | 9 +++------ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/lib/wpc/slip.c b/lib/wpc/slip.c index b61299c..32ec08c 100644 --- a/lib/wpc/slip.c +++ b/lib/wpc/slip.c @@ -155,7 +155,7 @@ int Slip_decode(uint8_t * buffer, size_t len) /* Compare CRC */ if (crc != crc_from_frame) { - LOG_PRINT_BUFFER(buffer, len); + LOG_PRINT_BUFFER(buffer, decoded_len - 2); LOGE("Wrong CRC 0x%04x (computed) vs 0x%04x (received)\n", crc, crc_from_frame); return WPC_INT_WRONG_CRC; } @@ -169,15 +169,15 @@ int Slip_encode(const uint8_t * buffer_in, size_t len_in, uint8_t * buffer_out, uint16_t crc = crc_fromBuffer(buffer_in, len_in); // Escape the frame without the CRC - size_t total_size = slip_encode_buffer(buffer_in, len_in, buffer_out, len_out); - - // Check that the buffer is big enough - if (total_size < 0) + int res = slip_encode_buffer(buffer_in, len_in, buffer_out, len_out); + if (res < 0) { LOGE("Provided buffer in encode is too small\n"); - return WPC_INT_WRONG_BUFFER_SIZE; + return res; } + size_t total_size = (size_t) res; + // Add the escaped CRC to the end of the buffer in little-endian byte order for (size_t i = 0; i < 2; i++) { diff --git a/lib/wpc/wpc.c b/lib/wpc/wpc.c index 869cd6b..6885f80 100644 --- a/lib/wpc/wpc.c +++ b/lib/wpc/wpc.c @@ -29,8 +29,7 @@ * \note Dual-MCU API return codes are not harmonized, so a * different look-up table must be used for each function */ -static inline app_res_e -convert_error_code(const app_res_e * lut, size_t lut_size, unsigned int error) +static inline app_res_e convert_error_code(const app_res_e * lut, size_t lut_size, int error) { app_res_e ret = APP_RES_INTERNAL_ERROR; if (error >= 0 && error < lut_size) @@ -774,7 +773,6 @@ static const app_res_e SCRATCHPAD_LOCAL_BLOCK_ERROR_CODE_LUT[] = { app_res_e WPC_upload_local_block_scratchpad(uint32_t len, uint8_t * bytes, uint32_t start) { app_res_e app_res; - int res; uint32_t loaded = 0; uint8_t max_block_size, block_size; @@ -792,14 +790,13 @@ app_res_e WPC_upload_local_block_scratchpad(uint32_t len, uint8_t * bytes, uint3 uint32_t addr_le; uint32_encode_le(start + loaded, (uint8_t *) &addr_le); - res = msap_scratchpad_block_request(addr_le, block_size, bytes + loaded); + int res = msap_scratchpad_block_request(addr_le, block_size, bytes + loaded); if (res > 1) { LOGE("Error in loading scratchpad block -> %d\n", res); return CONVERT_ERROR_CODE(SCRATCHPAD_LOCAL_BLOCK_ERROR_CODE_LUT, res); } - - if (res == 1) + else if (res == 1) { LOGD("Last block loaded\n"); } From 0fef4c3a93591e459069b95def054ab2f7ef9a1f Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Tue, 14 Jan 2020 12:18:38 -0500 Subject: [PATCH 13/21] Fix const pointer parameters in public and internal APIs Some pointer parameters didn't have the const qualifier even though the parameters were read-only. This commit adds the missing const qualifiers to the public and internal APIs. Please note: this commit changes the public API. The changes are mostly backward compatible, but some callback prototypes have changed. As a result, const qualifiers have to be added to any user-defined callback functions, or else the code won't compile. --- lib/api/logger.h | 14 +++++++------- lib/api/wpc.h | 19 ++++++++++--------- lib/platform/posix/logger.c | 16 ++++++++-------- lib/wpc/attribute.c | 2 +- lib/wpc/dsap.c | 4 ++-- lib/wpc/include/attribute.h | 2 +- lib/wpc/include/csap.h | 2 +- lib/wpc/include/dsap.h | 4 ++-- lib/wpc/include/msap.h | 23 ++++++++++++++--------- lib/wpc/include/wpc_internal.h | 2 +- lib/wpc/msap.c | 12 ++++++------ lib/wpc/wpc.c | 14 +++++++------- lib/wpc/wpc_internal.c | 2 +- test/test.c | 4 ++-- 14 files changed, 63 insertions(+), 57 deletions(-) diff --git a/lib/api/logger.h b/lib/api/logger.h index 8976c5c..afab327 100644 --- a/lib/api/logger.h +++ b/lib/api/logger.h @@ -44,7 +44,7 @@ * \param args * Argument for the string format */ -extern void Platform_LOG(char level, char * module, char * format, va_list args); +extern void Platform_LOG(char level, const char * module, const char * format, va_list args); /** * \brief Implemented in platform specific part to print a buffer @@ -53,7 +53,7 @@ extern void Platform_LOG(char level, char * module, char * format, va_list args) * \param size * the size of the buffer to print */ -extern void Platform_print_buffer(uint8_t * buffer, int size); +extern void Platform_print_buffer(const uint8_t * buffer, int size); /** * Macros to define several level of Log: Debug(3), Info(2), Warning(1), @@ -84,7 +84,7 @@ extern void Platform_print_buffer(uint8_t * buffer, int size); * Helpers macros to print logs */ #if MAX_LOG_LEVEL >= DEBUG_LOG_LEVEL -static inline void LOGD(char * format, ...) +static inline void LOGD(const char * format, ...) { va_list arg; va_start(arg, format); @@ -96,7 +96,7 @@ static inline void LOGD(char * format, ...) #endif #if MAX_LOG_LEVEL >= INFO_LOG_LEVEL -static inline void LOGI(char * format, ...) +static inline void LOGI(const char * format, ...) { va_list arg; va_start(arg, format); @@ -108,7 +108,7 @@ static inline void LOGI(char * format, ...) #endif #if MAX_LOG_LEVEL >= WARNING_LOG_LEVEL -static inline void LOGW(char * format, ...) +static inline void LOGW(const char * format, ...) { va_list arg; va_start(arg, format); @@ -120,7 +120,7 @@ static inline void LOGW(char * format, ...) #endif #if MAX_LOG_LEVEL >= ERROR_LOG_LEVEL -static inline void LOGE(char * format, ...) +static inline void LOGE(const char * format, ...) { va_list arg; va_start(arg, format); @@ -132,7 +132,7 @@ static inline void LOGE(char * format, ...) #endif #ifdef PRINT_BUFFERS -static inline void LOG_PRINT_BUFFER(uint8_t * buffer, int size) +static inline void LOG_PRINT_BUFFER(const uint8_t * buffer, int size) { Platform_print_buffer(buffer, size); } diff --git a/lib/api/wpc.h b/lib/api/wpc.h index 4afaef8..ddcf93d 100644 --- a/lib/api/wpc.h +++ b/lib/api/wpc.h @@ -221,7 +221,7 @@ typedef struct * \param bitrate * bitrate in bits per second, e.g. \ref DEFAULT_BITRATE */ -app_res_e WPC_initialize(char * port_name, unsigned long bitrate); +app_res_e WPC_initialize(const char * port_name, unsigned long bitrate); /** * \brief Stop the Wirepas Mesh serial communication @@ -339,7 +339,7 @@ app_res_e WPC_get_mesh_API_version(uint16_t * value_p); * The new key to set * \return Return code of the operation */ -app_res_e WPC_set_cipher_key(uint8_t key[16]); +app_res_e WPC_set_cipher_key(const uint8_t key[16]); /** * \brief Check if cipher key is set @@ -361,7 +361,7 @@ app_res_e WPC_remove_cipher_key(void); * The new key to set * \return Return code of the operation */ -app_res_e WPC_set_authentication_key(uint8_t key[16]); +app_res_e WPC_set_authentication_key(const uint8_t key[16]); /** * \brief Check if authentication key is set @@ -469,7 +469,8 @@ app_res_e WPC_get_app_config_data_size(uint8_t * value_p); * \return Return code of the operation * \note This call can only be made from a sink node */ -app_res_e WPC_set_app_config_data(uint8_t seq, uint16_t interval, uint8_t * config_p, uint8_t size); +app_res_e +WPC_set_app_config_data(uint8_t seq, uint16_t interval, const uint8_t * config_p, uint8_t size); /** * \brief Get app config data @@ -516,7 +517,7 @@ app_res_e WPC_get_sink_cost(uint8_t * cost_p); * Pointer to the received config data * Size is equal to returned size by WPC_get_app_config_data_size */ -typedef void (*onAppConfigDataReceived_cb_f)(uint8_t seq, uint16_t interval, uint8_t * config_p); +typedef void (*onAppConfigDataReceived_cb_f)(uint8_t seq, uint16_t interval, const uint8_t * config_p); /** * \brief Register for receiving app config data @@ -700,7 +701,7 @@ app_res_e WPC_start_local_scratchpad_update(uint32_t len, uint8_t seq); * Offset of the block relatively to the beginning of scratchpad * \return Return code of the operation */ -app_res_e WPC_upload_local_block_scratchpad(uint32_t len, uint8_t * bytes, uint32_t start); +app_res_e WPC_upload_local_block_scratchpad(uint32_t len, const uint8_t * bytes, uint32_t start); /** * \brief Upload a full scratchpad @@ -712,7 +713,7 @@ app_res_e WPC_upload_local_block_scratchpad(uint32_t len, uint8_t * bytes, uint3 * Sequence of the scratchpad to upload * \return Return code of the operation */ -app_res_e WPC_upload_local_scratchpad(uint32_t len, uint8_t * bytes, uint8_t seq); +app_res_e WPC_upload_local_scratchpad(uint32_t len, const uint8_t * bytes, uint8_t seq); /** * \brief Clear the local stored scratchpad @@ -808,7 +809,7 @@ app_res_e WPC_send_data(const uint8_t * bytes, * The message to send * \return Return code of the operation */ -app_res_e WPC_send_data_with_options(app_message_t * message_p); +app_res_e WPC_send_data_with_options(const app_message_t * message_p); /** * \brief Callback definition to register for received data @@ -876,7 +877,7 @@ app_res_e WPC_unregister_for_data(uint8_t dst_ep); * 0 means that no update request is ongoing */ typedef void (*onRemoteStatus_cb_f)(app_addr_t source_address, - app_scratchpad_status_t * status, + const app_scratchpad_status_t * status, uint16_t request_timeout); /** diff --git a/lib/platform/posix/logger.c b/lib/platform/posix/logger.c index a76683f..fcc84bf 100644 --- a/lib/platform/posix/logger.c +++ b/lib/platform/posix/logger.c @@ -9,10 +9,10 @@ #include /* Full log level string */ -static char DEBUG[] = "DEBUG"; -static char INFO[] = "INFO"; -static char WARNING[] = "WARNING"; -static char ERROR[] = "ERROR"; +static const char * DEBUG = "DEBUG"; +static const char * INFO = "INFO"; +static const char * WARNING = "WARNING"; +static const char * ERROR = "ERROR"; static inline void get_timestamp(char timestamp[37]) { @@ -39,10 +39,10 @@ static inline void get_timestamp(char timestamp[37]) ms); } -static inline void print_prefix(char level, char * module) +static inline void print_prefix(char level, const char * module) { char timestamp[37]; - char * full_level; + const char * full_level; switch (level) { @@ -65,13 +65,13 @@ static inline void print_prefix(char level, char * module) printf("%s | [%s] %s:", timestamp, full_level, module); } -void Platform_LOG(char level, char * module, char * format, va_list args) +void Platform_LOG(char level, const char * module, const char * format, va_list args) { print_prefix(level, module); vprintf(format, args); } -void Platform_print_buffer(uint8_t * buffer, int size) +void Platform_print_buffer(const uint8_t * buffer, int size) { int i; for (i = 0; i < size; i++) diff --git a/lib/wpc/attribute.c b/lib/wpc/attribute.c index a2f9984..e9c5b95 100644 --- a/lib/wpc/attribute.c +++ b/lib/wpc/attribute.c @@ -15,7 +15,7 @@ int attribute_write_request(uint8_t primitive_id, uint16_t attribute_id, uint8_t attribute_length, - uint8_t * attribute_value_p) + const uint8_t * attribute_value_p) { int res; wpc_frame_t request, confirm; diff --git a/lib/wpc/dsap.c b/lib/wpc/dsap.c index 1cc9d7a..09ea7d7 100644 --- a/lib/wpc/dsap.c +++ b/lib/wpc/dsap.c @@ -183,7 +183,7 @@ int dsap_data_tx_request(const uint8_t * buffer, return confirm_res; } -void dsap_data_tx_indication_handler(dsap_data_tx_ind_pl_t * payload) +void dsap_data_tx_indication_handler(const dsap_data_tx_ind_pl_t * payload) { onDataSent_cb_f cb = get_indication_cb(payload->pdu_id); @@ -200,7 +200,7 @@ void dsap_data_tx_indication_handler(dsap_data_tx_ind_pl_t * payload) } } -void dsap_data_rx_indication_handler(dsap_data_rx_ind_pl_t * payload, +void dsap_data_rx_indication_handler(const dsap_data_rx_ind_pl_t * payload, unsigned long long timestamp_ms_epoch) { uint32_t internal_travel_time = uint32_decode_le((uint8_t *) &(payload->travel_time)); diff --git a/lib/wpc/include/attribute.h b/lib/wpc/include/attribute.h index 1e90eeb..4973175 100644 --- a/lib/wpc/include/attribute.h +++ b/lib/wpc/include/attribute.h @@ -62,7 +62,7 @@ PACKED_STRUCT_END int attribute_write_request(uint8_t primitive_id, uint16_t attribute_id, uint8_t attribute_length, - uint8_t * attribute_value_p); + const uint8_t * attribute_value_p); /** * \brief Request to read an attribute from the stack * \param primitive_id diff --git a/lib/wpc/include/csap.h b/lib/wpc/include/csap.h index 83cf2bc..1f9b5ff 100644 --- a/lib/wpc/include/csap.h +++ b/lib/wpc/include/csap.h @@ -60,7 +60,7 @@ PACKED_STRUCT_END */ static inline int csap_attribute_write_request(uint16_t attribute_id, uint8_t attribute_length, - uint8_t * attribute_value_p) + const uint8_t * attribute_value_p) { return attribute_write_request(CSAP_ATTRIBUTE_WRITE_REQUEST, attribute_id, attribute_length, attribute_value_p); } diff --git a/lib/wpc/include/dsap.h b/lib/wpc/include/dsap.h index beb3948..e95c4f2 100644 --- a/lib/wpc/include/dsap.h +++ b/lib/wpc/include/dsap.h @@ -122,7 +122,7 @@ int dsap_data_tx_request(const uint8_t * buffer, * \brief Handler for tx indication. It is called when sent data leaves the * node \param payload Pointer to payload */ -void dsap_data_tx_indication_handler(dsap_data_tx_ind_pl_t * payload); +void dsap_data_tx_indication_handler(const dsap_data_tx_ind_pl_t * payload); /** * \brief Handler for rx indication @@ -131,7 +131,7 @@ void dsap_data_tx_indication_handler(dsap_data_tx_ind_pl_t * payload); * \param timestamp * Timestamp of reception of rx reception */ -void dsap_data_rx_indication_handler(dsap_data_rx_ind_pl_t * rx_indication, +void dsap_data_rx_indication_handler(const dsap_data_rx_ind_pl_t * rx_indication, unsigned long long timestamp_ms_epoch); /** diff --git a/lib/wpc/include/msap.h b/lib/wpc/include/msap.h index 240d9b6..2511741 100644 --- a/lib/wpc/include/msap.h +++ b/lib/wpc/include/msap.h @@ -206,7 +206,7 @@ PACKED_STRUCT_END static inline void convert_internal_to_app_scratchpad_status(app_scratchpad_status_t * status_p, - msap_scratchpad_status_conf_pl_t * internal_status_p) + const msap_scratchpad_status_conf_pl_t * internal_status_p) { // Copy internal payload to app return code. Cannot use memcpy as structures // may have different alignment @@ -237,7 +237,7 @@ convert_internal_to_app_scratchpad_status(app_scratchpad_status_t * status_p, */ static inline void convert_internal_to_app_neighbors_status(app_nbors_t * neighbors_p, - msap_get_nbors_conf_pl_t * internal_neighbors_p) + const msap_get_nbors_conf_pl_t * internal_neighbors_p) { // Copy internal payload to app return code. Cannot use memcpy as structures // may have different alignment @@ -289,7 +289,10 @@ int msap_stack_stop_request(void); * \return negative value if the request fails, * a Mesh positive result otherwise */ -int msap_app_config_data_write_request(uint8_t seq, uint16_t interval, uint8_t * config_p, uint8_t size); +int msap_app_config_data_write_request(uint8_t seq, + uint16_t interval, + const uint8_t * config_p, + uint8_t size); /** * \brief Request to read data config @@ -364,7 +367,9 @@ int msap_scratchpad_start_request(uint32_t length, uint8_t seq); * \return negative value if the request fails, * a Mesh positive result otherwise */ -int msap_scratchpad_block_request(uint32_t start_address, uint8_t number_of_bytes, uint8_t * bytes); +int msap_scratchpad_block_request(uint32_t start_address, + uint8_t number_of_bytes, + const uint8_t * bytes); /** * \brief Get the status of currently stored and processed scratchpad @@ -416,7 +421,7 @@ int msap_scratchpad_remote_update(app_addr_t destination_address, uint8_t sequen static inline int msap_attribute_write_request(uint16_t attribute_id, uint8_t attribute_length, - uint8_t * attribute_value_p) + const uint8_t * attribute_value_p) { return attribute_write_request(MSAP_ATTRIBUTE_WRITE_REQUEST, attribute_id, attribute_length, attribute_value_p); } @@ -433,28 +438,28 @@ static inline int msap_attribute_read_request(uint16_t attribute_id, * \param payload * pointer to payload */ -void msap_stack_state_indication_handler(msap_stack_state_ind_pl_t * payload); +void msap_stack_state_indication_handler(const msap_stack_state_ind_pl_t * payload); /** * \brief Handler for app config data receive * \param payload * pointer to payload */ -void msap_app_config_data_rx_indication_handler(msap_app_config_data_rx_ind_pl_t * payload); +void msap_app_config_data_rx_indication_handler(const msap_app_config_data_rx_ind_pl_t * payload); /** * \brief Handler for image remote status indication * \param payload * pointer to payload */ -void msap_image_remote_status_indication_handler(msap_image_remote_status_ind_pl_t * payload); +void msap_image_remote_status_indication_handler(const msap_image_remote_status_ind_pl_t * payload); /** * \brief Handler for scan neighbors indication * \param payload * pointer to payload */ -void msap_scan_nbors_indication_handler(msap_scan_nbors_ind_pl_t * payload); +void msap_scan_nbors_indication_handler(const msap_scan_nbors_ind_pl_t * payload); /** * \brief Register for app config data diff --git a/lib/wpc/include/wpc_internal.h b/lib/wpc/include/wpc_internal.h index bae3a31..d524348 100644 --- a/lib/wpc/include/wpc_internal.h +++ b/lib/wpc/include/wpc_internal.h @@ -82,7 +82,7 @@ int WPC_Int_get_indication(unsigned int max_ind, onIndicationReceivedLocked_cb_f */ void WPC_Int_dispatch_indication(wpc_frame_t * frame, unsigned long long timestamp_ms); -int WPC_Int_initialize(char * port_name, unsigned long bitrate); +int WPC_Int_initialize(const char * port_name, unsigned long bitrate); void WPC_Int_close(void); diff --git a/lib/wpc/msap.c b/lib/wpc/msap.c index 40e8029..7ff4b55 100644 --- a/lib/wpc/msap.c +++ b/lib/wpc/msap.c @@ -86,7 +86,7 @@ int msap_stack_stop_request() return confirm.payload.sap_generic_confirm_payload.result; } -int msap_app_config_data_write_request(uint8_t seq, uint16_t interval, uint8_t * config_p, uint8_t size) +int msap_app_config_data_write_request(uint8_t seq, uint16_t interval, const uint8_t * config_p, uint8_t size) { wpc_frame_t request, confirm; int res; @@ -248,7 +248,7 @@ int msap_scratchpad_start_request(uint32_t length, uint8_t seq) return confirm.payload.sap_generic_confirm_payload.result; } -int msap_scratchpad_block_request(uint32_t start_address, uint8_t number_of_bytes, uint8_t * bytes) +int msap_scratchpad_block_request(uint32_t start_address, uint8_t number_of_bytes, const uint8_t * bytes) { wpc_frame_t request, confirm; int res; @@ -375,7 +375,7 @@ int msap_scratchpad_remote_update(app_addr_t destination_address, uint8_t sequen return confirm.payload.sap_generic_confirm_payload.result; } -void msap_stack_state_indication_handler(msap_stack_state_ind_pl_t * payload) +void msap_stack_state_indication_handler(const msap_stack_state_ind_pl_t * payload) { LOGI("Status is 0x%02x\n", payload->status); if (m_stack_status_cb != NULL) @@ -384,7 +384,7 @@ void msap_stack_state_indication_handler(msap_stack_state_ind_pl_t * payload) } } -void msap_app_config_data_rx_indication_handler(msap_app_config_data_rx_ind_pl_t * payload) +void msap_app_config_data_rx_indication_handler(const msap_app_config_data_rx_ind_pl_t * payload) { LOGD("Received config data : [%s] (%d)\n", payload->app_config_data, payload->diag_data_interval); if (m_app_conf_cb != NULL) @@ -395,7 +395,7 @@ void msap_app_config_data_rx_indication_handler(msap_app_config_data_rx_ind_pl_t } } -void msap_image_remote_status_indication_handler(msap_image_remote_status_ind_pl_t * payload) +void msap_image_remote_status_indication_handler(const msap_image_remote_status_ind_pl_t * payload) { app_scratchpad_status_t app_status; LOGI("Received remote status from %d\n", payload->source_address); @@ -406,7 +406,7 @@ void msap_image_remote_status_indication_handler(msap_image_remote_status_ind_pl } } -void msap_scan_nbors_indication_handler(msap_scan_nbors_ind_pl_t * payload) +void msap_scan_nbors_indication_handler(const msap_scan_nbors_ind_pl_t * payload) { LOGI("Received scan neighbors ind res %d\n", payload->scan_ready); if (m_scan_neighbor_cb != NULL) diff --git a/lib/wpc/wpc.c b/lib/wpc/wpc.c index 6885f80..d7a2668 100644 --- a/lib/wpc/wpc.c +++ b/lib/wpc/wpc.c @@ -45,7 +45,7 @@ static inline app_res_e convert_error_code(const app_res_e * lut, size_t lut_siz #define CONVERT_ERROR_CODE(lut, error) \ convert_error_code(lut, sizeof(lut), error) -app_res_e WPC_initialize(char * port_name, unsigned long bitrate) +app_res_e WPC_initialize(const char * port_name, unsigned long bitrate) { return WPC_Int_initialize(port_name, bitrate) == 0 ? APP_RES_OK : APP_RES_INTERNAL_ERROR; } @@ -227,7 +227,7 @@ app_res_e WPC_get_firmware_version(uint16_t version[4]) return APP_RES_OK; } -app_res_e WPC_set_cipher_key(uint8_t key[16]) +app_res_e WPC_set_cipher_key(const uint8_t key[16]) { int res = csap_attribute_write_request(C_CIPHER_KEY_ID, 16, key); @@ -256,7 +256,7 @@ app_res_e WPC_remove_cipher_key(void) return WPC_set_cipher_key(disable_key); } -app_res_e WPC_set_authentication_key(uint8_t key[16]) +app_res_e WPC_set_authentication_key(const uint8_t key[16]) { int res = csap_attribute_write_request(C_AUTH_KEY_ID, 16, key); return CONVERT_ERROR_CODE(ATT_WRITE_ERROR_CODE_LUT, res); @@ -428,7 +428,7 @@ static const app_res_e APP_CONFIG_WRITE_ERROR_CODE_LUT[] = { APP_RES_ACCESS_DENIED // 4 }; -app_res_e WPC_set_app_config_data(uint8_t seq, uint16_t interval, uint8_t * config, uint8_t size) +app_res_e WPC_set_app_config_data(uint8_t seq, uint16_t interval, const uint8_t * config, uint8_t size) { uint16_t interval_le; uint16_encode_le(interval, (uint8_t *) &interval_le); @@ -725,7 +725,7 @@ app_res_e WPC_get_local_scratchpad_status(app_scratchpad_status_t * status_p) return APP_RES_OK; } -app_res_e WPC_upload_local_scratchpad(uint32_t len, uint8_t * bytes, uint8_t seq) +app_res_e WPC_upload_local_scratchpad(uint32_t len, const uint8_t * bytes, uint8_t seq) { app_res_e res; @@ -770,7 +770,7 @@ static const app_res_e SCRATCHPAD_LOCAL_BLOCK_ERROR_CODE_LUT[] = { APP_RES_INVALID_SCRATCHPAD // 7 }; -app_res_e WPC_upload_local_block_scratchpad(uint32_t len, uint8_t * bytes, uint32_t start) +app_res_e WPC_upload_local_block_scratchpad(uint32_t len, const uint8_t * bytes, uint32_t start) { app_res_e app_res; uint32_t loaded = 0; @@ -915,7 +915,7 @@ static const app_res_e SEND_DATA_ERROR_CODE_LUT[] = { APP_RES_INVALID_VALUE, // 9 APP_RES_ACCESS_DENIED // 10 }; -app_res_e WPC_send_data_with_options(app_message_t * message_t) +app_res_e WPC_send_data_with_options(const app_message_t * message_t) { int res; uint32_t dst_addr_le; diff --git a/lib/wpc/wpc_internal.c b/lib/wpc/wpc_internal.c index 48d0b0e..ee86d9c 100644 --- a/lib/wpc/wpc_internal.c +++ b/lib/wpc/wpc_internal.c @@ -309,7 +309,7 @@ int WPC_Int_send_request(wpc_frame_t * frame, wpc_frame_t * confirm) return WPC_Int_send_request_timeout(frame, confirm, TIMEOUT_CONFIRM_MS); } -int WPC_Int_initialize(char * port_name, unsigned long bitrate) +int WPC_Int_initialize(const char * port_name, unsigned long bitrate) { // Open the serial connection if (Serial_open(port_name, bitrate) < 0) diff --git a/test/test.c b/test/test.c index 3a09e6b..6be2cdd 100644 --- a/test/test.c +++ b/test/test.c @@ -348,7 +348,7 @@ static bool testSendWithInitialTime() return true; } -static void onAppConfigDataReceived(uint8_t seq, uint16_t interval, uint8_t * config_p) +static void onAppConfigDataReceived(uint8_t seq, uint16_t interval, const uint8_t * config_p) { LOGI("AppConfig received %d, %d, %s\n", seq, interval, config_p); } @@ -631,7 +631,7 @@ bool testLoadScratchpad() } static void onRemoteStatusCb(app_addr_t source_address, - app_scratchpad_status_t * status, + const app_scratchpad_status_t * status, uint16_t request_timeout) { LOGI("Received status from %d with tiemout to %d\n", source_address, request_timeout); From 01c15eb26e28081431f53f56b67001d2ec0a791f Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Tue, 14 Jan 2020 12:38:37 -0500 Subject: [PATCH 14/21] Add more missing "void" in function prototypes and definitions --- lib/platform/posix/platform.c | 12 +++++----- lib/platform/posix/serial_posix.c | 2 +- lib/wpc/csap.c | 2 +- lib/wpc/dsap.c | 2 +- lib/wpc/msap.c | 16 ++++++------- test/test.c | 37 ++++++++++++++++--------------- 6 files changed, 36 insertions(+), 35 deletions(-) diff --git a/lib/platform/posix/platform.c b/lib/platform/posix/platform.c index f1170b3..fe7cfa7 100644 --- a/lib/platform/posix/platform.c +++ b/lib/platform/posix/platform.c @@ -149,7 +149,7 @@ static void onIndicationReceivedLocked(wpc_frame_t * frame, unsigned long long t /** * \brief Utility function to get current timesatmp in s. */ -static time_t get_timestamp_s() +static time_t get_timestamp_s(void) { struct timespec spec; @@ -253,7 +253,7 @@ void Platform_usleep(unsigned int time_us) usleep(time_us); } -bool Platform_lock_request() +bool Platform_lock_request(void) { int res = pthread_mutex_lock(&sending_mutex); if (res != 0) @@ -266,12 +266,12 @@ bool Platform_lock_request() return true; } -void Platform_unlock_request() +void Platform_unlock_request(void) { pthread_mutex_unlock(&sending_mutex); } -unsigned long long Platform_get_timestamp_ms_epoch() +unsigned long long Platform_get_timestamp_ms_epoch(void) { struct timespec spec; @@ -280,7 +280,7 @@ unsigned long long Platform_get_timestamp_ms_epoch() return ((unsigned long long) spec.tv_sec) * 1000 + (spec.tv_nsec) / 1000 / 1000; } -bool Platform_init() +bool Platform_init(void) { /* This linux implementation uses a dedicated thread * to poll for indication. The indication are then handled @@ -346,7 +346,7 @@ bool Platform_set_max_poll_fail_duration(unsigned long duration_s) return true; } -void Platform_close() +void Platform_close(void) { pthread_mutex_destroy(&m_queue_mutex); pthread_mutex_destroy(&sending_mutex); diff --git a/lib/platform/posix/serial_posix.c b/lib/platform/posix/serial_posix.c index 67f12dd..ae83332 100644 --- a/lib/platform/posix/serial_posix.c +++ b/lib/platform/posix/serial_posix.c @@ -110,7 +110,7 @@ int Serial_open(const char * port_name, unsigned long bitrate) return 0; } -int Serial_close() +int Serial_close(void) { if (fd < 0) { diff --git a/lib/wpc/csap.c b/lib/wpc/csap.c index eb105f8..5789fc9 100644 --- a/lib/wpc/csap.c +++ b/lib/wpc/csap.c @@ -15,7 +15,7 @@ static const uint8_t reset_key_le[4] = {0x44, 0x6f, 0x49, 0x74}; // DoIt in ascii in LE -int csap_factory_reset_request() +int csap_factory_reset_request(void) { wpc_frame_t request, confirm; int res; diff --git a/lib/wpc/dsap.c b/lib/wpc/dsap.c index 09ea7d7..f518769 100644 --- a/lib/wpc/dsap.c +++ b/lib/wpc/dsap.c @@ -272,7 +272,7 @@ bool dsap_unregister_for_data(uint8_t dst_ep) return ret; } -void dsap_init() +void dsap_init(void) { // Initialize internal structures memset(data_cb_table, 0, sizeof(data_cb_table)); diff --git a/lib/wpc/msap.c b/lib/wpc/msap.c index 7ff4b55..bfc4253 100644 --- a/lib/wpc/msap.c +++ b/lib/wpc/msap.c @@ -69,7 +69,7 @@ int msap_stack_start_request(uint8_t start_option) return confirm.payload.sap_generic_confirm_payload.result; } -int msap_stack_stop_request() +int msap_stack_stop_request(void) { wpc_frame_t request, confirm; int res; @@ -208,7 +208,7 @@ int msap_get_nbors_request(msap_get_nbors_conf_pl_t * neigbors_p) return APP_RES_OK; } -int msap_scan_nbors_request() +int msap_scan_nbors_request(void) { wpc_frame_t request, confirm; int res; @@ -299,7 +299,7 @@ int msap_scratchpad_status_request(msap_scratchpad_status_conf_pl_t * status_p) return APP_RES_OK; } -int msap_scratchpad_update_request() +int msap_scratchpad_update_request(void) { wpc_frame_t request, confirm; int res; @@ -317,7 +317,7 @@ int msap_scratchpad_update_request() return confirm.payload.sap_generic_confirm_payload.result; } -int msap_scratchpad_clear_request() +int msap_scratchpad_clear_request(void) { wpc_frame_t request, confirm; int res; @@ -443,7 +443,7 @@ bool msap_register_for_app_config(onAppConfigDataReceived_cb_f cb) return register_cb((void *) cb, (void **) &m_app_conf_cb); } -bool msap_unregister_from_app_config() +bool msap_unregister_from_app_config(void) { return unregister_cb((void **) &m_app_conf_cb); } @@ -453,7 +453,7 @@ bool msap_register_for_remote_status(onRemoteStatus_cb_f cb) return register_cb((void *) cb, (void **) &m_remote_status_cb); } -bool msap_unregister_from_remote_status() +bool msap_unregister_from_remote_status(void) { return unregister_cb((void **) &m_remote_status_cb); } @@ -463,7 +463,7 @@ bool msap_register_for_scan_neighbors_done(onScanNeighborsDone_cb_f cb) return register_cb((void *) cb, (void **) &m_scan_neighbor_cb); } -bool msap_unregister_from_scan_neighbors_done() +bool msap_unregister_from_scan_neighbors_done(void) { return unregister_cb((void **) &m_scan_neighbor_cb); } @@ -473,7 +473,7 @@ bool msap_register_for_stack_status(onStackStatusReceived_cb_f cb) return register_cb((void *) cb, (void **) &m_stack_status_cb); } -bool msap_unregister_from_stack_status() +bool msap_unregister_from_stack_status(void) { return unregister_cb((void **) &m_stack_status_cb); } diff --git a/test/test.c b/test/test.c index 6be2cdd..1a7a322 100644 --- a/test/test.c +++ b/test/test.c @@ -3,6 +3,7 @@ * See file LICENSE for full license details. * */ + #include #include @@ -39,7 +40,7 @@ static bool setInitialState(app_role_t role, return true; } -static bool testFactoryReset() +static bool testFactoryReset(void) { app_res_e res = WPC_stop_stack(); app_addr_t add; @@ -110,7 +111,7 @@ static bool setAppconfig(uint8_t * config, uint16_t interval, uint8_t size) return true; } -static bool dumpCSAPAttributes() +static bool dumpCSAPAttributes(void) { uint8_t role; net_channel_t channel; @@ -175,7 +176,7 @@ static bool dumpCSAPAttributes() return true; } -static bool testCipherKey() +static bool testCipherKey(void) { bool key_set; if (WPC_is_cipher_key_set(&key_set) != APP_RES_OK) @@ -234,7 +235,7 @@ static bool testCipherKey() return true; } -static bool testAuthenticationKey() +static bool testAuthenticationKey(void) { bool key_set; if (WPC_is_authentication_key_set(&key_set) != APP_RES_OK) @@ -298,7 +299,7 @@ void onDataSent(uint16_t pduid, uint32_t buffering_delay, uint8_t result) LOGI("Indication received for %d, delay=%d, result=%d\n", pduid, buffering_delay, result); } -static bool testSendWithCallbacks() +static bool testSendWithCallbacks(void) { // Send 5 message to ourself uint8_t data[] = "This is a test message #00 with ind\0"; @@ -315,7 +316,7 @@ static bool testSendWithCallbacks() return true; } -static bool testSendWithoutCallbacks() +static bool testSendWithoutCallbacks(void) { // Send 5 message to ourself uint8_t data[] = "This is a test message #00\0"; @@ -331,7 +332,7 @@ static bool testSendWithoutCallbacks() return true; } -static bool testSendWithInitialTime() +static bool testSendWithInitialTime(void) { // Send 5 message to ourself uint8_t data[] = "This is a test message #00\0"; @@ -353,7 +354,7 @@ static void onAppConfigDataReceived(uint8_t seq, uint16_t interval, const uint8_ LOGI("AppConfig received %d, %d, %s\n", seq, interval, config_p); } -static bool testAppConfigData() +static bool testAppConfigData(void) { uint8_t new_config[128]; uint8_t max_size; @@ -383,7 +384,7 @@ static bool testAppConfigData() return true; } -static bool testMSAPAttributesStackOff() +static bool testMSAPAttributesStackOff(void) { uint16_t min, max; // Access cycle @@ -429,7 +430,7 @@ static bool testMSAPAttributesStackOff() return true; } -static bool testMSAPAttributesStackOn() +static bool testMSAPAttributesStackOn(void) { uint8_t res8; uint16_t res16; @@ -516,7 +517,7 @@ static bool testMSAPAttributesStackOn() return true; } -bool testClearScratchpad() +bool testClearScratchpad(void) { app_scratchpad_status_t status; if (WPC_clear_local_scratchpad() != APP_RES_OK) @@ -543,7 +544,7 @@ bool testClearScratchpad() #define BLOCK_SIZE 128 #define SEQ_NUMBER 50 #define OTAP_FILE_PATH "source/test/scratchpad_nrf52.otap" -bool testLoadScratchpad() +bool testLoadScratchpad(void) { FILE * fp; app_scratchpad_status_t status; @@ -642,7 +643,7 @@ static void onRemoteStatusCb(app_addr_t source_address, status->processed_scrat_crc); } -static bool testRemoteStatus() +static bool testRemoteStatus(void) { if (WPC_register_for_remote_status(onRemoteStatusCb) != APP_RES_OK) { @@ -672,7 +673,7 @@ static bool testRemoteStatus() return true; } -static bool testRemoteUpdate() +static bool testRemoteUpdate(void) { // Send a update with a 0 reboot delay to just test the command if (WPC_remote_scratchpad_update(APP_ADDR_BROADCAST, 50, 0) != APP_RES_OK) @@ -692,7 +693,7 @@ static void onScanNeighborsDone(uint8_t status) scan_done = true; } -static bool testScanNeighbors() +static bool testScanNeighbors(void) { app_nbors_t neighbors_list; @@ -757,7 +758,7 @@ static void onStackStatusReceived(uint8_t status) LOGI("Stack status received %d\n", status); } -static bool testStackStatus() +static bool testStackStatus(void) { if (WPC_register_for_stack_status(onStackStatusReceived) != APP_RES_OK) { @@ -781,7 +782,7 @@ static bool testStackStatus() } \ } while (0) -int Test_runAll() +int Test_runAll(void) { uint8_t status; @@ -833,7 +834,7 @@ int Test_runAll() return 0; } -int Test_scratchpad() +int Test_scratchpad(void) { // Configure node as a sink setInitialState(APP_ROLE_SINK, 1234, 0x654321, 5, false); From 290df871f1ce5fd2e9fe7a05be7d594f10137862 Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Tue, 14 Jan 2020 12:58:28 -0500 Subject: [PATCH 15/21] Improve inconsistent log messages Some log message formatting and wording was inconsistent, so it was improved. Also, a couple of potential bugs related to logging were fixed, as well as some typos in comments. --- example/main.c | 2 +- lib/platform/darwin/serial_darwin.c | 2 +- lib/platform/linux/serial_linux.c | 2 +- lib/platform/posix/logger.c | 33 +++++++++++++++++------------ lib/platform/posix/platform.c | 2 +- lib/platform/posix/serial_posix.c | 22 +++++++++---------- lib/wpc/dsap.c | 11 ++++++---- lib/wpc/include/wpc_internal.h | 2 +- lib/wpc/include/wpc_types.h | 2 +- lib/wpc/slip.c | 6 +++--- test/test.c | 2 +- test/test_app.c | 2 +- 12 files changed, 48 insertions(+), 40 deletions(-) diff --git a/example/main.c b/example/main.c index d634978..5207ac7 100644 --- a/example/main.c +++ b/example/main.c @@ -11,7 +11,7 @@ #include "wpc.h" -#define LOG_MODULE_NAME "Main" +#define LOG_MODULE_NAME "example_main" #define MAX_LOG_LEVEL INFO_LOG_LEVEL #include "logger.h" diff --git a/lib/platform/darwin/serial_darwin.c b/lib/platform/darwin/serial_darwin.c index 545d0a8..eb237f3 100644 --- a/lib/platform/darwin/serial_darwin.c +++ b/lib/platform/darwin/serial_darwin.c @@ -10,7 +10,7 @@ #include "posix/serial_posix.h" -#define LOG_MODULE_NAME "SERIAL" +#define LOG_MODULE_NAME "serial_darwin" #define MAX_LOG_LEVEL DEBUG_LOG_LEVEL #include "logger.h" diff --git a/lib/platform/linux/serial_linux.c b/lib/platform/linux/serial_linux.c index dea575d..15fb126 100644 --- a/lib/platform/linux/serial_linux.c +++ b/lib/platform/linux/serial_linux.c @@ -12,7 +12,7 @@ #include "posix/serial_posix.h" -#define LOG_MODULE_NAME "SERIAL" +#define LOG_MODULE_NAME "serial_linux" #define MAX_LOG_LEVEL DEBUG_LOG_LEVEL #include "logger.h" diff --git a/lib/platform/posix/logger.c b/lib/platform/posix/logger.c index fcc84bf..d27fdd1 100644 --- a/lib/platform/posix/logger.c +++ b/lib/platform/posix/logger.c @@ -14,7 +14,7 @@ static const char * INFO = "INFO"; static const char * WARNING = "WARNING"; static const char * ERROR = "ERROR"; -static inline void get_timestamp(char timestamp[37]) +static inline void get_timestamp(char * buffer, size_t size) { struct tm result; long ms; @@ -28,20 +28,22 @@ static inline void get_timestamp(char timestamp[37]) ms = spec.tv_nsec / 1.0e6; // Convert nanoseconds to milliseconds - sprintf(timestamp, - "%d-%02d-%02d %02d:%02d:%02d,%03ld", - result.tm_year + 1900, // tm_year is in year - 1900 - result.tm_mon + 1, // tm_mon is in [0-11] - result.tm_mday, - result.tm_hour, - result.tm_min, - result.tm_sec, - ms); + snprintf(buffer, + size, + "%04d-%02d-%02d %02d:%02d:%02d.%03ld", + result.tm_year + 1900, // tm_year is in year - 1900 + result.tm_mon + 1, // tm_mon is in [0-11] + result.tm_mday, + result.tm_hour, + result.tm_min, + result.tm_sec, + ms); } static inline void print_prefix(char level, const char * module) { - char timestamp[37]; + char timestamp[24]; + char level_buf[2]; const char * full_level; switch (level) @@ -59,10 +61,13 @@ static inline void print_prefix(char level, const char * module) full_level = ERROR; break; default: - full_level = &level; + level_buf[0] = level; + level_buf[1] = '\0'; + full_level = level_buf; + break; } - get_timestamp(timestamp); - printf("%s | [%s] %s:", timestamp, full_level, module); + get_timestamp(timestamp, sizeof(timestamp)); + printf("%s | [%s] %s: ", timestamp, full_level, module); } void Platform_LOG(char level, const char * module, const char * format, va_list args) diff --git a/lib/platform/posix/platform.c b/lib/platform/posix/platform.c index fe7cfa7..b74cd36 100644 --- a/lib/platform/posix/platform.c +++ b/lib/platform/posix/platform.c @@ -10,7 +10,7 @@ #include #include -#define LOG_MODULE_NAME "linux_plat" +#define LOG_MODULE_NAME "plat_posix" #define MAX_LOG_LEVEL INFO_LOG_LEVEL #include "logger.h" #include "wpc_internal.h" diff --git a/lib/platform/posix/serial_posix.c b/lib/platform/posix/serial_posix.c index ae83332..3c72bca 100644 --- a/lib/platform/posix/serial_posix.c +++ b/lib/platform/posix/serial_posix.c @@ -14,7 +14,7 @@ #include "serial_posix.h" -#define LOG_MODULE_NAME "SERIAL" +#define LOG_MODULE_NAME "serial_posix" #define MAX_LOG_LEVEL INFO_LOG_LEVEL #include "logger.h" @@ -94,7 +94,7 @@ int Serial_open(const char * port_name, unsigned long bitrate) fd = open(port_name, O_RDWR | O_NOCTTY | O_SYNC); if (fd < 0) { - LOGE("Error %d opening serial link %s: %s\n", errno, port_name, strerror(errno)); + LOGE("Error %d opening serial port %s: %s\n", errno, port_name, strerror(errno)); return -1; } @@ -106,7 +106,7 @@ int Serial_open(const char * port_name, unsigned long bitrate) return -1; } - LOGD("Serial opened\n"); + LOGD("Serial port opened\n"); return 0; } @@ -114,18 +114,18 @@ int Serial_close(void) { if (fd < 0) { - LOGW("Link already closed\n"); + LOGE("Serial port not open\n"); return -1; } if (close(fd) < 0) { - LOGW("Error %d closing serial link: %s\n", errno, strerror(errno)); + LOGW("Error %d closing serial port: %s\n", errno, strerror(errno)); return -1; } fd = -1; - LOGD("Serial closed\n"); + LOGD("Serial port closed\n"); return 0; } @@ -137,7 +137,7 @@ int Serial_read(unsigned char * c, unsigned int timeout_ms) if (fd < 0) { - LOGE("No serial link opened\n"); + LOGE("Serial port not open\n"); return -1; } @@ -163,18 +163,18 @@ int Serial_read(unsigned char * c, unsigned int timeout_ms) } else { - LOGE("Problem in serial read, fd not set\n"); + LOGE("Problem in serial port read, fd not set\n"); return -1; } } else if (retval == 0) { - LOGD("Timeout to wait for char on serial line\n"); + LOGD("Timeout to wait for char on serial port\n"); return 0; } else { - LOGE("Error in Serial read %d\n", retval); + LOGE("Error in Serial port read %d\n", retval); return -1; } } @@ -183,7 +183,7 @@ int Serial_write(const unsigned char * buffer, size_t buffer_size) { if (fd < 0) { - LOGE("No serial link opened\n"); + LOGE("Serial port not open\n"); return -1; } diff --git a/lib/wpc/dsap.c b/lib/wpc/dsap.c index f518769..725f60f 100644 --- a/lib/wpc/dsap.c +++ b/lib/wpc/dsap.c @@ -207,12 +207,15 @@ void dsap_data_rx_indication_handler(const dsap_data_rx_ind_pl_t * payload, app_qos_e qos; uint8_t hop_count; - LOGI("Data received: indication_status = %d, src_add = %d, lenght=%u, " - "travel time = %d, dst_ep = %d, ts=%llu\n", + LOGI("Data received: indication_status = %u, src_add = %lu, " + "dest_add = %lu, lenght= %u, travel time = %lu, " + "src_ep = %u, dst_ep = %u, ts = %llu\n", payload->indication_status, - payload->src_add, + (unsigned long) payload->src_add, + (unsigned long) payload->dest_add, payload->apdu_length, - internal_travel_time, + (unsigned long) internal_travel_time, + payload->src_endpoint, payload->dest_endpoint, timestamp_ms_epoch); diff --git a/lib/wpc/include/wpc_internal.h b/lib/wpc/include/wpc_internal.h index d524348..8a360c5 100644 --- a/lib/wpc/include/wpc_internal.h +++ b/lib/wpc/include/wpc_internal.h @@ -23,7 +23,7 @@ typedef enum * \param frame * The received indication * \param timestamp_ms - * Timestamp of teh received indication + * Timestamp of the received indication */ typedef void (*onIndicationReceivedLocked_cb_f)(wpc_frame_t * frame, unsigned long long timestamp_ms); diff --git a/lib/wpc/include/wpc_types.h b/lib/wpc/include/wpc_types.h index 6fe1bb6..13ffb08 100644 --- a/lib/wpc/include/wpc_types.h +++ b/lib/wpc/include/wpc_types.h @@ -99,7 +99,7 @@ PACKED_STRUCT_END // Size of a given frame #define FRAME_SIZE(__frame_ptr__) ((__frame_ptr__)->payload_length + 3) -// Max frame size (including crc) +// Max frame size (including CRC) #define MAX_FRAME_SIZE (sizeof(wpc_frame_t) + 2) // Define the function type to handle a received frame from the stack (confirm diff --git a/lib/wpc/slip.c b/lib/wpc/slip.c index 32ec08c..fa99f7b 100644 --- a/lib/wpc/slip.c +++ b/lib/wpc/slip.c @@ -7,7 +7,7 @@ #include #include -#define LOG_MODULE_NAME "SLIP" +#define LOG_MODULE_NAME "slip" #define MAX_LOG_LEVEL INFO_LOG_LEVEL //#define PRINT_BUFFERS #include "logger.h" @@ -295,7 +295,7 @@ int Slip_get_buffer(uint8_t * buffer, size_t len, unsigned int timeout_ms) else if (start_of_frame_detected) { #ifdef PRINT_RECEIVED_CHAR - LOG_PRINT_BUFFER(&read, 1); + LOG_PRINT_BUFFER(&read_byte, 1); #endif if (size >= sizeof(receiving_buffer)) { @@ -308,7 +308,7 @@ int Slip_get_buffer(uint8_t * buffer, size_t len, unsigned int timeout_ms) } else { - LOGD("Receiving bytes between messages 0x%02x\n", read); + LOGD("Receiving bytes between messages 0x%02x\n", read_byte); } } // End of while(1) diff --git a/test/test.c b/test/test.c index 1a7a322..1ec78aa 100644 --- a/test/test.c +++ b/test/test.c @@ -7,7 +7,7 @@ #include #include -#define LOG_MODULE_NAME "Test" +#define LOG_MODULE_NAME "test" #define MAX_LOG_LEVEL INFO_LOG_LEVEL #include "logger.h" diff --git a/test/test_app.c b/test/test_app.c index 8a1bf81..76ef651 100644 --- a/test/test_app.c +++ b/test/test_app.c @@ -12,7 +12,7 @@ #include "test.h" #include "wpc.h" -#define LOG_MODULE_NAME "TestApp" +#define LOG_MODULE_NAME "test_app" #define MAX_LOG_LEVEL INFO_LOG_LEVEL #include "logger.h" From 73482339067d94f4ebd7b8b17c75b2976809261b Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Tue, 14 Jan 2020 13:03:50 -0500 Subject: [PATCH 16/21] Add more error checks to POSIX serial port routines Some error situations were not properly handled, so a couple of check were added. --- lib/platform/linux/serial_linux.c | 9 ++++++--- lib/platform/posix/serial_posix.c | 6 ++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/platform/linux/serial_linux.c b/lib/platform/linux/serial_linux.c index 15fb126..77f1d7a 100644 --- a/lib/platform/linux/serial_linux.c +++ b/lib/platform/linux/serial_linux.c @@ -51,9 +51,12 @@ int Serial_set_extra_params(int fd) // On FTDI USB adapters it reduces the latency timer to 1 ms from the // default of 16 ms. See Part III of the FTDI application note // "AN232B-04 Data Throughput, Latency and Handshaking" for details - ioctl(fd, TIOCGSERIAL, &serial_s); - serial_s.flags |= ASYNC_LOW_LATENCY; - ioctl(fd, TIOCSSERIAL, &serial_s); + if (ioctl(fd, TIOCGSERIAL, &serial_s) >= 0) + { + serial_s.flags |= ASYNC_LOW_LATENCY; + ioctl(fd, TIOCSSERIAL, &serial_s); + } + // Errors are not fatal return 0; } diff --git a/lib/platform/posix/serial_posix.c b/lib/platform/posix/serial_posix.c index 3c72bca..424d753 100644 --- a/lib/platform/posix/serial_posix.c +++ b/lib/platform/posix/serial_posix.c @@ -91,6 +91,12 @@ static int set_interface_attribs(int fd, unsigned long bitrate, int parity) /****************************************************************************/ int Serial_open(const char * port_name, unsigned long bitrate) { + if (fd >= 0) + { + LOGE("Serial port already open\n"); + return -1; + } + fd = open(port_name, O_RDWR | O_NOCTTY | O_SYNC); if (fd < 0) { From 4239cd55f6f280163b06ab6d45fac65f01f82a31 Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Tue, 14 Jan 2020 16:56:26 -0500 Subject: [PATCH 17/21] Unconditionally compile Wirepas C Mesh API library with examples Even if the library file already exists, run make in the lib/ directory. This ensures that any changes to the library are compiled as well. --- example/gnu_make.mk | 4 ++-- test/gnu_make.mk | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/example/gnu_make.mk b/example/gnu_make.mk index df16157..a5551e7 100644 --- a/example/gnu_make.mk +++ b/example/gnu_make.mk @@ -60,13 +60,13 @@ endif .PHONY: all all: app -app: $(TARGET_APP) +app: lib $(TARGET_APP) .PHONY: clean clean: $(call CLEAN) -$(MESH_LIB): +lib: make -C $(MESH_LIB_FOLDER) $(BUILDPREFIX)/%.o: $(SOURCEPREFIX)/%.c diff --git a/test/gnu_make.mk b/test/gnu_make.mk index 839a72c..86bfa29 100644 --- a/test/gnu_make.mk +++ b/test/gnu_make.mk @@ -31,8 +31,8 @@ CFLAGS += -I$(SOURCEPREFIX) SOURCES += $(SOURCEPREFIX)/test.c # Object files -OBJECTS := $(patsubst $(SOURCEPREFIX)/%, \ - $(BUILDPREFIX)/%, \ +OBJECTS := $(patsubst $(SOURCEPREFIX)/%, \ + $(BUILDPREFIX)/%, \ $(SOURCES:.c=.o)) @@ -68,13 +68,13 @@ endif .PHONY: all all: app -app: $(TARGET_APP) +app: lib $(TARGET_APP) .PHONY: clean clean: $(call CLEAN) -$(MESH_LIB): +lib: make -C $(MESH_LIB_FOLDER) $(BUILDPREFIX)/%.o: $(SOURCEPREFIX)/%.c From b119b1fae5eaf908a2d81cf746938924383ea265 Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Tue, 14 Jan 2020 22:11:41 -0500 Subject: [PATCH 18/21] Add support for Win32 This commit adds serial port, thread and logging support for Windows. --- lib/nmake.mk | 8 +- lib/platform/posix/platform.c | 2 +- lib/platform/win32/logger.c | 68 +++++- lib/platform/win32/platform.c | 363 ++++++++++++++++++++++++++++-- lib/platform/win32/serial_win32.c | 194 ++++++++++++++-- lib/wpc/wpc.c | 2 +- 6 files changed, 595 insertions(+), 42 deletions(-) diff --git a/lib/nmake.mk b/lib/nmake.mk index 0c17b77..e8d7cf1 100644 --- a/lib/nmake.mk +++ b/lib/nmake.mk @@ -18,16 +18,18 @@ LDFLAGS = $(LDFLAGS) PLATFORM_IS_WIN32 = 1 CFLAGS = $(CFLAGS) /DPLATFORM_IS_WIN32=1 -# Path of source files +# Path of source files and build outputs SOURCEPREFIX = . +BUILDPREFIX = build # Uncomment the following line only if running with an old stack #CFLAGS += /DLEGACY_APP_CONFIG=1 # Targets definition LIB_NAME = mesh_api_lib -TARGET_LIB = build\$(LIB_NAME).lib +TARGET_LIB = $(BUILDPREFIX)\$(LIB_NAME).lib +# Source files SOURCES = # Add API header (including logger) and internal headers @@ -59,7 +61,7 @@ lib: $(TARGET_LIB) clean: echo Cleaning up - -del $(OBJECTS) >NUL 2>NUL + -del /F $(OBJECTS) $(TARGET_LIB) >NUL 2>NUL -rmdir /S /Q $(BUILDPREFIX) >NUL 2>NUL .c.obj: diff --git a/lib/platform/posix/platform.c b/lib/platform/posix/platform.c index b74cd36..a00da24 100644 --- a/lib/platform/posix/platform.c +++ b/lib/platform/posix/platform.c @@ -244,7 +244,7 @@ static void * poll_for_indication(void * unused) LOGE("Exiting polling thread\n"); // Full process must be exited if uart doesnt' work - exit(EXIT_FAILURE); + exit(EXIT_FAILURE); // TODO: Don't do this return NULL; } diff --git a/lib/platform/win32/logger.c b/lib/platform/win32/logger.c index 2e8bcde..0428078 100644 --- a/lib/platform/win32/logger.c +++ b/lib/platform/win32/logger.c @@ -4,21 +4,69 @@ * */ +#include #include #include +#include -void Platform_LOG(char level, char * module, char * format, va_list args) +static inline void get_timestamp(char * buffer, size_t size) { - // TODO - (void) level; - (void) module; - (void) format; - (void) args; + SYSTEMTIME now; + GetLocalTime(&now); + snprintf(buffer, + size, + "%04u-%02u-%02u %02u:%02u:%02u.%03u", + (unsigned int) now.wYear, + (unsigned int) now.wMonth, + (unsigned int) now.wDay, + (unsigned int) now.wHour, + (unsigned int) now.wMinute, + (unsigned int) now.wSecond, + (unsigned int) now.wMilliseconds); } -void Platform_print_buffer(uint8_t * buffer, int size) +void Platform_LOG(char level, const char * module, const char * format, va_list args) { - // TODO - (void) buffer; - (void) size; + char timestamp[24]; + char desc_buf[2]; + const char * level_desc; + + if (level == 'D') + { + level_desc = "DEBUG"; + } + else if (level == 'I') + { + level_desc = "INFO"; + } + else if (level == 'W') + { + level_desc = "WARNING"; + } + else if (level == 'E') + { + level_desc = "ERROR"; + } + else + { + desc_buf[0] = level; + desc_buf[1] = '\0'; + level_desc = desc_buf; + } + + get_timestamp(timestamp, sizeof(timestamp)); + printf("%s | [%s] %s: ", timestamp, level_desc, module); + vprintf(format, args); +} + +void Platform_print_buffer(const uint8_t * buffer, int size) +{ + int i; + for (i = 0; i < size; i++) + { + if ((i & 0xF) == 0xF) + printf("\n"); + printf("%02x ", buffer[i]); + } + printf("\n"); } diff --git a/lib/platform/win32/platform.c b/lib/platform/win32/platform.c index 8f683ce..115672b 100644 --- a/lib/platform/win32/platform.c +++ b/lib/platform/win32/platform.c @@ -4,50 +4,385 @@ * */ +#include // For NULL +#include // For memcpy() #include +#include -#define LOG_MODULE_NAME "linux_plat" +#define LOG_MODULE_NAME "plat_win32" #define MAX_LOG_LEVEL INFO_LOG_LEVEL #include "logger.h" +#include "platform.h" #include "wpc_internal.h" +// Maximum number of indication to be retrieved from a single poll +#define MAX_NUMBER_INDICATION 30 + +// Polling interval to check for indication +#define POLLING_INTERVAL_MS 20 + +// Maximum duration in s of failed poll request to declare the link broken +// (unplugged) Set it to 0 to disable 60 sec is long period but it must cover +// the OTAP exchange with neighbors that can be long with some profiles +#define DEFAULT_MAX_POLL_FAIL_DURATION_S 60 + +// Critical section for sending, i.e. serial port access +static CRITICAL_SECTION m_sending_cs; + +// This thread is used to poll for indication +static HANDLE thread_polling = NULL; + +// This thread is used to dispatch indication +static HANDLE thread_dispatch = NULL; + +// Last successful poll request +static time_t m_last_successful_poll_ts; +static unsigned int m_max_poll_fail_duration_s; + +/*****************************************************************************/ +/* Indication queue related variables */ +/*****************************************************************************/ + +// Size of the queue between getter and dispatcher of indication +// In most of the cases, the dispatcher is supposed to be faster and the +// queue will have only one element +// But if some execution handling are too long or require to send something over +// UART, the dispatching thread will be hanged until the poll thread finish its +// work +#define MAX_NUMBER_INDICATION_QUEUE (MAX_NUMBER_INDICATION * 2) + +// Struct that describes a received frame with its timestamp +typedef struct +{ + wpc_frame_t frame; //< The received frame + unsigned long long timestamp_ms_epoch; //< The timestamp of reception +} timestamped_frame_t; + +// Indications queue +static timestamped_frame_t m_indications_queue[MAX_NUMBER_INDICATION_QUEUE]; + +// Head of the queue for the polling thread to write +static volatile unsigned int m_ind_queue_write = 0; + +// Tail of the queue to read from dispatching thread +static volatile unsigned int m_ind_queue_read = 0; + +// Is queue empty? +static volatile bool m_queue_empty = true; + +// Critical section and condition variable +// used for the dispatching queue to wait +static CRITICAL_SECTION m_queue_cs; +static CONDITION_VARIABLE m_queue_not_empty_cond; + +/*****************************************************************************/ +/* Dispatch indication Thread implementation */ +/*****************************************************************************/ +/** + * \brief Thread to dispatch indication in a non locked environment + */ +static DWORD WINAPI dispatch_indication(LPVOID unused) +{ + (void) unused; + + LOGD("Dispatch thread started\n"); + + // Acquire ownership of queue critical section initially + EnterCriticalSection(&m_queue_cs); + + while (true) + { + while (m_queue_empty) + { + // Queue is empty, release ownership and wait + SleepConditionVariableCS(&m_queue_not_empty_cond, &m_queue_cs, INFINITE); + } + + // Get the oldest indication + timestamped_frame_t * ind = &m_indications_queue[m_ind_queue_read]; + + // Handle the indication without the queue critical section + LeaveCriticalSection(&m_queue_cs); + + // Dispatch the indication + WPC_Int_dispatch_indication(&ind->frame, ind->timestamp_ms_epoch); + + // Re-acquire ownership of queue critical section, to update empty + // status and wait on condition again in next loop iteration + EnterCriticalSection(&m_queue_cs); + + m_ind_queue_read = (m_ind_queue_read + 1) % MAX_NUMBER_INDICATION_QUEUE; + if (m_ind_queue_read == m_ind_queue_write) + { + // Indication was the last one + m_queue_empty = true; + } + } + + LOGE("Exiting dispatch thread\n"); + return 0; +} + +/*****************************************************************************/ +/* Polling Thread implementation */ +/*****************************************************************************/ +static void onIndicationReceivedLocked(wpc_frame_t * frame, unsigned long long timestamp_ms) +{ + LOGD("Frame received with timestamp = %llu\n", timestamp_ms); + + // Acquire ownership of queue critical section, to + // add an indication and update the empty status + EnterCriticalSection(&m_queue_cs); + + // Check if queue is full + if (!m_queue_empty && (m_ind_queue_write == m_ind_queue_read)) + { + // Queue is FULL + LOGE("No more room for indications! Must never happen!\n"); + } + else + { + // Insert our received indication + timestamped_frame_t * ind = &m_indications_queue[m_ind_queue_write]; + memcpy(&ind->frame, frame, sizeof(wpc_frame_t)); + ind->timestamp_ms_epoch = timestamp_ms; + + m_ind_queue_write = (m_ind_queue_write + 1) % MAX_NUMBER_INDICATION_QUEUE; + // At least one indication ready, signal it + m_queue_empty = false; + WakeConditionVariable(&m_queue_not_empty_cond); + } + + // Handle the indication without the queue critical section + LeaveCriticalSection(&m_queue_cs); +} + +/** + * \brief Utility function to get current timestamp in seconds + */ +static time_t get_timestamp_s(void) +{ + return Platform_get_timestamp_ms_epoch() / 1000; +} + +/** + * \brief Polling tread + * This thread polls for indication and insert them to the queue + * shared with the dispatcher thread + */ +static DWORD WINAPI poll_for_indication(void * unused) +{ + (void) unused; + + LOGD("Polling thread started\n"); + + unsigned int max_num_indication, free_buffer_room; + int get_ind_res; + uint32_t wait_before_next_polling_ms = 0; + + while (true) + { + Platform_usleep(wait_before_next_polling_ms * 1000); + + /* Ask for maximum room in buffer queue and less than MAX */ + if (!m_queue_empty && (m_ind_queue_write == m_ind_queue_read)) + { + // Queue is FULL, wait for POLLING INTERVALL to give some + // time for the dispatching thread to handle them + LOGW("Queue is full, do not poll\n"); + wait_before_next_polling_ms = POLLING_INTERVAL_MS; + continue; + } + else if (m_queue_empty) + { + // Queue is empty + free_buffer_room = MAX_NUMBER_INDICATION_QUEUE; + } + else + { + // Queue has elements, determine the number of free buffers + if (m_ind_queue_write > m_ind_queue_read) + { + free_buffer_room = MAX_NUMBER_INDICATION_QUEUE - + (m_ind_queue_write - m_ind_queue_read); + } + else + { + free_buffer_room = m_ind_queue_read - m_ind_queue_write; + } + } + + max_num_indication = free_buffer_room > MAX_NUMBER_INDICATION ? + MAX_NUMBER_INDICATION : + free_buffer_room; + + LOGD("Poll for %d indications\n", max_num_indication); + + get_ind_res = WPC_Int_get_indication(max_num_indication, onIndicationReceivedLocked); + + if (get_ind_res == 1) + { + // Still pending indication, only wait 1 ms to give a chance + // to other threads but not more to have better throughput + wait_before_next_polling_ms = 1; + } + else + { + // In case of error or if no more indication, just wait + // the POLLING INTERVAL to avoid polling all the time + wait_before_next_polling_ms = POLLING_INTERVAL_MS; + } + + if (m_max_poll_fail_duration_s > 0) + { + if (get_ind_res >= 0 || get_ind_res == WPC_INT_SYNC_ERROR) + { + // Poll request executed fine or at least com is working with sink, + // reset fail counter + m_last_successful_poll_ts = get_timestamp_s(); + } + else + { + if (get_timestamp_s() - m_last_successful_poll_ts > m_max_poll_fail_duration_s) + { + // Poll request has failed for too long, just exit + break; + } + } + } + } + + LOGE("Exiting polling thread\n"); + + // Full process must be exited if uart doesnt' work + exit(EXIT_FAILURE); // TODO: Don't do this +} + void Platform_usleep(unsigned int time_us) { - // TODO - (void) time_us; + Sleep((time_us + 999) / 1000); // Sleep at least 1 ms } bool Platform_lock_request(void) { - // TODO - return false; + EnterCriticalSection(&m_sending_cs); + return true; } void Platform_unlock_request(void) { - // TODO + LeaveCriticalSection(&m_sending_cs); } unsigned long long Platform_get_timestamp_ms_epoch(void) { - // TODO - return 0ULL; + // Get system time + SYSTEMTIME now; + GetSystemTime(&now); + FILETIME filetime; + + // Convert to filetime, i.e. 100-nanosecond + // intervals since January 1, 1601 (UTC) + if (!SystemTimeToFileTime(&now, &filetime)) + { + // Could not get time + return 0ULL; + } + + // Convert to 64 bits + ULARGE_INTEGER timestamp; + memcpy(×tamp, &filetime, sizeof(FILETIME)); + + // Return milliseconds since epoch (not UNIX epoch) + return timestamp.QuadPart / 10000; } bool Platform_init(void) { - // TODO - return false; + /* This win32 implementation uses a dedicated thread + * to poll for indication. The indication are then handled + * by this thread. + * All the other API calls can be made on different threads + * as this platform implements the lock mechanism in order + * to protect the access to critical sections. + */ + + // Initialize a condition variable for queue not empty + InitializeConditionVariable(&m_queue_not_empty_cond); + + // Initialize a crical section to access queue + InitializeCriticalSection(&m_queue_cs); + + // Create a crical section to access serial port + InitializeCriticalSection(&m_sending_cs); + + // Start a thread to poll for indication + thread_polling = CreateThread(NULL, // Default security attributes + 0, // Default stack size + poll_for_indication, // Thread function + NULL, // Arguments to thread function + 0, // Default creation flags + NULL); // Do not store thread ID + if (!thread_polling) + { + LOGE("Cannot create polling thread\n"); + Platform_close(); + return false; + } + + // Start a thread to dispatch indication + thread_dispatch = CreateThread(NULL, // Default security attributes + 0, // Default stack size + dispatch_indication, // Thread function + NULL, // Arguments to thread function + 0, // Default creation flags + NULL); // Do not store thread ID + if (!thread_dispatch) + { + LOGE("Cannot create dispatch thread\n"); + Platform_close(); + return false; + } + + m_last_successful_poll_ts = get_timestamp_s(); + m_max_poll_fail_duration_s = DEFAULT_MAX_POLL_FAIL_DURATION_S; + + return true; } bool Platform_set_max_poll_fail_duration(unsigned long duration_s) { - // TODO - (void) duration_s; - return false; + if ((m_max_poll_fail_duration_s == 0) && (duration_s > 0)) + { + m_last_successful_poll_ts = get_timestamp_s(); + } + m_max_poll_fail_duration_s = duration_s; + return true; } void Platform_close(void) { - // TODO + if (thread_dispatch) + { + // TODO: Request dispatch thread to exit + + // Wait for dispatch thread to exit + WaitForSingleObject(thread_dispatch, INFINITE); + + // Close dispatch thread handle to free allocated resources + CloseHandle(thread_dispatch); + thread_dispatch = NULL; + } + + if (thread_polling) + { + // TODO: Request polling thread to exit + + // Wait for polling thread to exit + WaitForSingleObject(thread_polling, INFINITE); + + // Close polling thread handle to free allocated resources + CloseHandle(thread_polling); + thread_polling = NULL; + } } diff --git a/lib/platform/win32/serial_win32.c b/lib/platform/win32/serial_win32.c index 3aff22a..7d699c0 100644 --- a/lib/platform/win32/serial_win32.c +++ b/lib/platform/win32/serial_win32.c @@ -5,33 +5,201 @@ */ #include +#include +#include +#include + +#define LOG_MODULE_NAME "serial_win32" +#define MAX_LOG_LEVEL INFO_LOG_LEVEL +#include "logger.h" + +static HANDLE serial_port_handle = INVALID_HANDLE_VALUE; + +#if MAX_LOG_LEVEL >= ERROR_LOG_LEVEL + +static char * format_error(unsigned long error) +{ + char * buffer = NULL; + + if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, // Flags + NULL, // Source (ignored) + error, // Message ID + 0, // Language ID: automatic + (LPTSTR) &buffer, // Allocated buffer + 256, // Minimum allocate buffer size + NULL) == 0) // Arguments (ignored) + { + buffer = NULL; + } + + return buffer; +} + +static void free_error(char * buffer) +{ + if (buffer) + { + LocalFree(buffer); + } +} + +static void print_last_error(const char * info) +{ + unsigned long last_error = GetLastError(); + char * buffer = format_error(last_error); + LOGE("Error 0x%lx %s: %s\n", last_error, info, buffer ? buffer : "unknown error"); + free_error(buffer); +} + +#else // MAX_LOG_LEVEL >= ERROR_LOG_LEVEL +# define print_last_error(message) +#endif // MAX_LOG_LEVEL >= ERROR_LOG_LEVEL int Serial_open(const char * port_name, unsigned long bitrate) { - // TODO - (void) port_name; - (void) bitrate; + if (serial_port_handle != INVALID_HANDLE_VALUE) + { + LOGE("Serial port already open\n"); + return -1; + } + + // Convert port name to Win32 device namespace form + char filename_buf[MAX_PATH]; + const char * ns_prefix = "\\\\.\\"; + if (strncmp(port_name, ns_prefix, 4) == 0) + { + // Port name is already in Win32 device namespace + ns_prefix = ""; + } + snprintf(filename_buf, MAX_PATH, "%s%s", ns_prefix, port_name); + + // Open serial port + serial_port_handle = CreateFileA(filename_buf, // Port filename + GENERIC_READ | GENERIC_WRITE, // Read/Write + 0, // No sharing + NULL, // No security + OPEN_EXISTING, // Open existing port only + 0, // Non-overlapped I/O + NULL); // NULL for comm devices + + if (serial_port_handle == INVALID_HANDLE_VALUE) + { + char buffer[MAX_PATH + 40]; + snprintf(buffer, sizeof(buffer), "opening serial port %s", port_name); + print_last_error(buffer); + return -1; + } + + // Initialize an empty DCB + DCB dcb = {0}; + dcb.DCBlength = sizeof(DCB); + + // Create a settings string for BuildCommDCBA() + char param_buf[80]; + snprintf(param_buf, sizeof(param_buf), "baud=%lu parity=N data=8 stop=1", bitrate); + + // Create a timeout struct for SetCommTimeouts() + COMMTIMEOUTS timeouts = {0}; + timeouts.ReadIntervalTimeout = MAXDWORD; // Immediate + + // Configure serial port + if (!BuildCommDCBA(param_buf, &dcb)) + { + print_last_error("calling BuildCommDCBA"); + } + else if (!SetCommState(serial_port_handle, &dcb)) + { + print_last_error("calling SetCommState"); + } + else if (!SetCommTimeouts(serial_port_handle, &timeouts)) + { + print_last_error("calling SetCommTimeouts"); + } + else + { + LOGD("Serial port opened\n"); + return 0; + } + + // Error setting serial port parameters, close port and leave + CloseHandle(serial_port_handle); + serial_port_handle = INVALID_HANDLE_VALUE; return -1; } int Serial_close(void) { - // TODO - return -1; + if (serial_port_handle == INVALID_HANDLE_VALUE) + { + LOGE("Serial port not open\n"); + return -1; + } + + if (!CloseHandle(serial_port_handle)) + { + print_last_error("closing serial port"); + return -1; + } + + serial_port_handle = INVALID_HANDLE_VALUE; + LOGD("Serial port closed\n"); + return 0; } int Serial_read(unsigned char * c, unsigned int timeout_ms) { - // TODO - (void) c; - (void) timeout_ms; - return 0; + if (serial_port_handle == INVALID_HANDLE_VALUE) + { + LOGE("Serial port not open\n"); + return -1; + } + + // Create a timeout struct for SetCommTimeouts() + COMMTIMEOUTS timeouts = {0}; + timeouts.ReadIntervalTimeout = 0; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.ReadTotalTimeoutConstant = timeout_ms; + + // Set read timeout + if (!SetCommTimeouts(serial_port_handle, &timeouts)) + { + print_last_error("calling SetCommTimeouts"); + return -1; + } + + // Read one byte from serial port, with timeout + DWORD num_bytes; + if (!ReadFile(serial_port_handle, c, 1, &num_bytes, NULL)) + { + print_last_error("calling ReadFile"); + return -1; + } + else if (num_bytes == 0) + { + LOGD("Timeout to wait for char on serial port\n"); + } + + return (int) num_bytes; } int Serial_write(const unsigned char * buffer, size_t buffer_size) { - // TODO - (void) buffer; - (void) buffer_size; - return 0; + if (serial_port_handle == INVALID_HANDLE_VALUE) + { + LOGE("Serial port not open\n"); + return -1; + } + + DWORD num_bytes; + if (!WriteFile(serial_port_handle, buffer, buffer_size, &num_bytes, NULL)) + { + print_last_error("calling WriteFile"); + return -1; + } + else if (num_bytes < buffer_size) + { + LOGW("Short write to serial port\n"); + } + + return (int) num_bytes; } diff --git a/lib/wpc/wpc.c b/lib/wpc/wpc.c index d7a2668..83bb5d4 100644 --- a/lib/wpc/wpc.c +++ b/lib/wpc/wpc.c @@ -32,7 +32,7 @@ static inline app_res_e convert_error_code(const app_res_e * lut, size_t lut_size, int error) { app_res_e ret = APP_RES_INTERNAL_ERROR; - if (error >= 0 && error < lut_size) + if (error >= 0 && (size_t) error < lut_size) { ret = lut[error]; } From cc723ceea8306f8ba071d35686c1a7c12f23bc73 Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Tue, 14 Jan 2020 22:32:48 -0500 Subject: [PATCH 19/21] Add Win32 support to test applications Add NMAKE makefiles and some small fixes to compile cleanly. --- example/main.c | 56 ++++++++++++++++++++++++++++++---- example/nmake.mk | 70 +++++++++++++++++++++++++++++++++++++++++++ test/nmake.mk | 78 ++++++++++++++++++++++++++++++++++++++++++++++++ test/test.c | 44 +++++++++++++++++---------- test/test_app.c | 1 - 5 files changed, 227 insertions(+), 22 deletions(-) create mode 100644 example/nmake.mk create mode 100644 test/nmake.mk diff --git a/example/main.c b/example/main.c index 5207ac7..46f708d 100644 --- a/example/main.c +++ b/example/main.c @@ -7,7 +7,14 @@ #include #include #include -#include + +#ifdef PLATFORM_IS_WIN32 +# include // For Sleep() +# define sleep(sec) Sleep(sec * 1000) +# define pause() Sleep(500) +#else +# include // For sleep(), pause() +#endif #include "wpc.h" @@ -16,7 +23,15 @@ #include "logger.h" // Default serial port -char * port_name = "/dev/ttyACM0"; +#ifdef PLATFORM_IS_WIN32 +static char * port_name = "COM1"; +#elif PLATFORM_IS_LINUX +static char * port_name = "/dev/ttyACM0"; +#elif PLATFORM_IS_DARWIN +static char * port_name = "/dev/cu.usbmodem0001234567890"; +#else +static char * port_name = "/dev/ttyS0"; +#endif // Node configuration #define NODE_ADDRESS 0x1 @@ -35,13 +50,26 @@ static bool onDataReceived(const uint8_t * bytes, uint8_t hop_count, unsigned long long timestamp_ms_epoch) { + // Suppress warnings for unused parameters + (void) bytes; + (void) num_bytes; + (void) src_addr; + (void) dst_addr; + (void) qos; + (void) src_ep; + (void) dst_ep; + (void) travel_time; + (void) hop_count; + (void) timestamp_ms_epoch; + // Handle Data received here - LOGI("Data received on EP %d of len %d with id %d from 0x%x to 0x%x\n", + LOGI("Data received on EP %u of len %u with id %u from %lu to %lu\n", dst_ep, num_bytes, bytes[0], - src_addr, - dst_addr); + (unsigned long) src_addr, + (unsigned long) dst_addr); + return true; } @@ -56,7 +84,25 @@ static bool onDiagReceived(const uint8_t * bytes, uint8_t hop_count, unsigned long long timestamp_ms_epoch) { + // Suppress warnings for unused parameters + (void) bytes; + (void) num_bytes; + (void) src_addr; + (void) dst_addr; + (void) qos; + (void) src_ep; + (void) dst_ep; + (void) travel_time; + (void) hop_count; + (void) timestamp_ms_epoch; + // Handle diag packet here + // Handle Data received here + LOGI("Diag received from EP %u of len %u from %lu to %lu\n", + src_ep, + num_bytes, + (unsigned long) src_addr, + (unsigned long) dst_addr); return true; } diff --git a/example/nmake.mk b/example/nmake.mk new file mode 100644 index 0000000..3ddeff4 --- /dev/null +++ b/example/nmake.mk @@ -0,0 +1,70 @@ +# Makefile for Wirepas C Mesh API example, Microsoft NMAKE version + +# This example needs the C Mesh API library +MESH_LIB_FOLDER = ..\lib +MESH_LIB = $(MESH_LIB_FOLDER)\build\mesh_api_lib.lib + +# Microsoft Visual studio command line toolchain on Windows +# Use Visual Studio defaults +#CC = cl +#AS = ml + +# Visual Studio C compiler flags +CFLAGS = $(CFLAGS) /nologo /W4 /WX /O2 /TC + +# Linker flags +LDFLAGS = $(LDFLAGS) /nologo + +# Platform flags +!MESSAGE Platform: WIN32 +PLATFORM_IS_WIN32 = 1 +CFLAGS = $(CFLAGS) /DPLATFORM_IS_WIN32=1 + +# Path of source files and build outputs +SOURCEPREFIX = . +BUILDPREFIX = build + +# Targets definition +MAIN_APP = meshAPIExample +TARGET_APP = $(BUILDPREFIX)\$(MAIN_APP).exe + +# Add API header +CFLAGS = $(CFLAGS) /I$(MESH_LIB_FOLDER)\api + +# Source files +SOURCES = $(SOURCEPREFIX)\main.c + +# Object files, one for each C source file +OBJECTS = $(SOURCES:.c=.obj) + + +# Target rules + +!IF "$(V)"=="1" + # "V=1" on command line, print commands +!MESSAGE SOURCES: $(SOURCES) +!MESSAGE OBJECTS: $(OBJECTS) +!ELSE +.SILENT:# Default, do not print commands +!ENDIF + +all: app + +app: lib $(TARGET_APP) + +clean: + echo Cleaning up + -del /F $(OBJECTS) $(TARGET_APP) >NUL 2>NUL + -rmdir /S /Q $(BUILDPREFIX) >NUL 2>NUL + +lib: + cd $(MESH_LIB_FOLDER) && $(MAKE) /nologo /f nmake.mk + +.c.obj: + -mkdir $(@D) >NUL 2>NUL + $(CC) $(CFLAGS) /c /Fo$@ $*.c + +$(TARGET_APP): $(OBJECTS) $(MESH_LIB) + echo Linking $@ + -mkdir $(@D) >NUL 2>NUL + $(CC) $(LDFLAGS) /Fe$@ $** diff --git a/test/nmake.mk b/test/nmake.mk new file mode 100644 index 0000000..272f4c0 --- /dev/null +++ b/test/nmake.mk @@ -0,0 +1,78 @@ +# Makefile for Wirepas C Mesh API test suite, Microsoft NMAKE version + +# This example needs the C Mesh API library +MESH_LIB_FOLDER = ..\lib +MESH_LIB = $(MESH_LIB_FOLDER)\build\mesh_api_lib.lib + +# Microsoft Visual studio command line toolchain on Windows +# Use Visual Studio defaults +#CC = cl +#AS = ml + +# Visual Studio C compiler flags +CFLAGS = $(CFLAGS) /nologo /W4 /WX /O2 /TC + +# Linker flags +LDFLAGS = $(LDFLAGS) /nologo + +# Platform flags +!MESSAGE Platform: WIN32 +PLATFORM_IS_WIN32 = 1 +CFLAGS = $(CFLAGS) /DPLATFORM_IS_WIN32=1 + +# Path of source files and build outputs +SOURCEPREFIX = . +BUILDPREFIX = build + +# Targets definition +MAIN_APP = meshAPItest +TARGET_APP = $(BUILDPREFIX)\$(MAIN_APP).exe + +# Add API header +CFLAGS = $(CFLAGS) /I$(MESH_LIB_FOLDER)\api + +# Test app needs some platform abstraction +# This is a hack and not really part of the C Mesh API library public API +CFLAGS = $(CFLAGS) /I$(MESH_LIB_FOLDER)\platform + +# Main app source file +SOURCES = $(SOURCEPREFIX)\test_app.c + +# Test case source files +CFLAGS = $(CFLAGS) /I$(SOURCEPREFIX) +SOURCES = $(SOURCES) $(SOURCEPREFIX)\test.c + +# Object files, one for each C source file +OBJECTS = $(SOURCES:.c=.obj) + + +# Target rules + +!IF "$(V)"=="1" + # "V=1" on command line, print commands +!MESSAGE SOURCES: $(SOURCES) +!MESSAGE OBJECTS: $(OBJECTS) +!ELSE +.SILENT:# Default, do not print commands +!ENDIF + +all: app + +app: lib $(TARGET_APP) + +clean: + echo Cleaning up + -del /F $(OBJECTS) $(TARGET_APP) >NUL 2>NUL + -rmdir /S /Q $(BUILDPREFIX) >NUL 2>NUL + +lib: + cd $(MESH_LIB_FOLDER) && $(MAKE) /nologo /f nmake.mk + +.c.obj: + -mkdir $(@D) >NUL 2>NUL + $(CC) $(CFLAGS) /c /Fo$@ $*.c + +$(TARGET_APP): $(OBJECTS) $(MESH_LIB) + echo Linking $@ + -mkdir $(@D) >NUL 2>NUL + $(CC) $(LDFLAGS) /Fe$@ $** diff --git a/test/test.c b/test/test.c index 1ec78aa..6faac9c 100644 --- a/test/test.c +++ b/test/test.c @@ -14,6 +14,17 @@ #include "wpc.h" #include "platform.h" +#if PLATFORM_IS_WIN32 +# undef fopen +static inline FILE * win32_fopen(const char * name, const char * mode) +{ + FILE * f = NULL; + fopen_s(&f, name, mode); // MSVC gives a warning with plain fopen() + return f; +} +# define fopen(name, mode) win32_fopen(name, mode) +#endif + static bool setInitialState(app_role_t role, app_addr_t id, net_addr_t network_add, @@ -305,9 +316,9 @@ static bool testSendWithCallbacks(void) uint8_t data[] = "This is a test message #00 with ind\0"; for (int i = 0; i < 2; i++) { - data[24] = i / 10 + 0x30; - data[25] = i % 10 + 0x30; - if (WPC_send_data(data, sizeof(data), i, APP_ADDR_ANYSINK, APP_QOS_HIGH, 50, 50, onDataSent, 0) != + data[24] = (uint8_t)(i / 10 + 0x30); + data[25] = (uint8_t)(i % 10 + 0x30); + if (WPC_send_data(data, sizeof(data), (uint16_t) i, APP_ADDR_ANYSINK, APP_QOS_HIGH, 50, 50, onDataSent, 0) != APP_RES_OK) { return false; @@ -322,9 +333,10 @@ static bool testSendWithoutCallbacks(void) uint8_t data[] = "This is a test message #00\0"; for (int i = 2; i < 4; i++) { - data[24] = i / 10 + 0x30; - data[25] = i % 10 + 0x30; - if (WPC_send_data(data, sizeof(data), i, APP_ADDR_ANYSINK, APP_QOS_HIGH, 50, 50, NULL, 0) != APP_RES_OK) + data[24] = (uint8_t)(i / 10 + 0x30); + data[25] = (uint8_t)(i % 10 + 0x30); + if (WPC_send_data(data, sizeof(data), (uint16_t) i, APP_ADDR_ANYSINK, APP_QOS_HIGH, 50, 50, NULL, 0) != + APP_RES_OK) { return false; } @@ -338,9 +350,9 @@ static bool testSendWithInitialTime(void) uint8_t data[] = "This is a test message #00\0"; for (int i = 4; i < 6; i++) { - data[24] = i / 10 + 0x30; - data[25] = i % 10 + 0x30; - if (WPC_send_data(data, sizeof(data), i, APP_ADDR_ANYSINK, APP_QOS_HIGH, 50, 50, NULL, 300) != + data[24] = (uint8_t)(i / 10 + 0x30); + data[25] = (uint8_t)(i % 10 + 0x30); + if (WPC_send_data(data, sizeof(data), (uint16_t) i, APP_ADDR_ANYSINK, APP_QOS_HIGH, 50, 50, NULL, 300) != APP_RES_OK) { return false; @@ -570,13 +582,13 @@ bool testLoadScratchpad(void) LOGE("Cannot determine file size\n"); return false; } - LOGI("Loading otap file of %d bytes\n", file_size); + LOGI("Loading otap file of %ld bytes\n", file_size); /* Set cursor to beginning of file */ fseek(fp, 0L, SEEK_SET); /* Start scratchpad update*/ - if (WPC_start_local_scratchpad_update(file_size, SEQ_NUMBER) != APP_RES_OK) + if (WPC_start_local_scratchpad_update((uint32_t) file_size, SEQ_NUMBER) != APP_RES_OK) { LOGE("Cannot start scratchpad update\n"); return false; @@ -587,7 +599,7 @@ bool testLoadScratchpad(void) long remaining = file_size; while (remaining > 0) { - uint8_t block_size = (remaining > BLOCK_SIZE) ? BLOCK_SIZE : remaining; + uint8_t block_size = (uint8_t)((remaining > BLOCK_SIZE) ? BLOCK_SIZE : remaining); size_t read; read = fread(block, 1, block_size, fp); @@ -614,9 +626,9 @@ bool testLoadScratchpad(void) return false; } - if (status.scrat_len != file_size) + if (status.scrat_len != (uint32_t) file_size) { - LOGE("Scratchpad is not loaded correctly (wrong size) %d vs %d\n", + LOGE("Scratchpad is not loaded correctly (wrong size) %d vs %ld\n", status.scrat_len, file_size); return false; @@ -655,7 +667,7 @@ static bool testRemoteStatus(void) // TODO replace by getneighbors Platform_usleep(60 * 1000 * 1000); - if (WPC_get_remote_status(APP_ADDR_BROADCAST) != APP_RES_OK) + if (WPC_get_remote_status((app_addr_t) APP_ADDR_BROADCAST) != APP_RES_OK) { LOGE("Cannot send remote status\n"); return false; @@ -676,7 +688,7 @@ static bool testRemoteStatus(void) static bool testRemoteUpdate(void) { // Send a update with a 0 reboot delay to just test the command - if (WPC_remote_scratchpad_update(APP_ADDR_BROADCAST, 50, 0) != APP_RES_OK) + if (WPC_remote_scratchpad_update((app_addr_t) APP_ADDR_BROADCAST, 50, 0) != APP_RES_OK) { LOGE("Cannot send remote update\n"); return false; diff --git a/test/test_app.c b/test/test_app.c index 76ef651..a595a65 100644 --- a/test/test_app.c +++ b/test/test_app.c @@ -7,7 +7,6 @@ #include #include #include -#include #include "test.h" #include "wpc.h" From 5d9417512577301454b873860241356f3d9d6316 Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Fri, 17 Jan 2020 18:05:10 -0500 Subject: [PATCH 20/21] Change Win32 build flags to be compatible with official Python release In order to use the Wirepas C Mesh API library in a Python extension module, it has to be built with flags that are compatible with the official Python release for Windows. The default flag /MT ("link with LIBCMT.LIB") needs to be changed to /MD ("link with MSVCRT.LIB"). --- example/nmake.mk | 2 +- lib/nmake.mk | 2 +- test/nmake.mk | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/example/nmake.mk b/example/nmake.mk index 3ddeff4..b722140 100644 --- a/example/nmake.mk +++ b/example/nmake.mk @@ -10,7 +10,7 @@ MESH_LIB = $(MESH_LIB_FOLDER)\build\mesh_api_lib.lib #AS = ml # Visual Studio C compiler flags -CFLAGS = $(CFLAGS) /nologo /W4 /WX /O2 /TC +CFLAGS = $(CFLAGS) /nologo /W4 /WX /O2 /MD /TC # Linker flags LDFLAGS = $(LDFLAGS) /nologo diff --git a/lib/nmake.mk b/lib/nmake.mk index e8d7cf1..84d17dd 100644 --- a/lib/nmake.mk +++ b/lib/nmake.mk @@ -8,7 +8,7 @@ #AS = ml # Visual Studio C compiler flags -CFLAGS = $(CFLAGS) /nologo /W4 /WX /O2 /TC +CFLAGS = $(CFLAGS) /nologo /W4 /WX /O2 /MD /TC # Linker flags LDFLAGS = $(LDFLAGS) diff --git a/test/nmake.mk b/test/nmake.mk index 272f4c0..0c1c068 100644 --- a/test/nmake.mk +++ b/test/nmake.mk @@ -10,7 +10,7 @@ MESH_LIB = $(MESH_LIB_FOLDER)\build\mesh_api_lib.lib #AS = ml # Visual Studio C compiler flags -CFLAGS = $(CFLAGS) /nologo /W4 /WX /O2 /TC +CFLAGS = $(CFLAGS) /nologo /W4 /WX /O2 /MD /TC # Linker flags LDFLAGS = $(LDFLAGS) /nologo From 38a5e89e6afa155087bebc9cda5132f8323c1c31 Mon Sep 17 00:00:00 2001 From: jy-wirepas <59594181+jy-wirepas@users.noreply.github.com> Date: Fri, 17 Jan 2020 18:58:03 -0500 Subject: [PATCH 21/21] Makefile clean up Move Windows toolchain settings in a separate makefile fragment and harmonize the messages that are printed during the build for both GNU and Windows platforms. --- example/gnu_make.mk | 10 ++++++---- example/nmake.mk | 24 +++++++----------------- lib/gnu_make.mk | 6 +++--- lib/nmake.mk | 22 +++++----------------- lib/{platform.mk => tools.mk} | 0 lib/tools_msvc.mk | 17 +++++++++++++++++ test/gnu_make.mk | 10 ++++++---- test/nmake.mk | 24 +++++++----------------- 8 files changed, 51 insertions(+), 62 deletions(-) rename lib/{platform.mk => tools.mk} (100%) create mode 100644 lib/tools_msvc.mk diff --git a/example/gnu_make.mk b/example/gnu_make.mk index a5551e7..df2defe 100644 --- a/example/gnu_make.mk +++ b/example/gnu_make.mk @@ -1,11 +1,13 @@ # Makefile for Wirepas C Mesh API example, GNU make version +# Variables + # This example needs the C Mesh API library MESH_LIB_FOLDER := ../lib MESH_LIB := $(MESH_LIB_FOLDER)/build/mesh_api_lib.a # Detect platform and set toolchain variables -include $(MESH_LIB_FOLDER)/platform.mk +include $(MESH_LIB_FOLDER)/tools.mk # Path of source files and build outputs SOURCEPREFIX := . @@ -38,12 +40,12 @@ define COMPILE endef define LINK - echo " Linking $(1)" - $(CC) $(CFLAGS) $(LDFLAGS) -o $(1) $(2) $(MESH_LIB) + echo " LD $(1)" + $(CC) $(LDFLAGS) -o $(1) $(2) $(MESH_LIB) endef define CLEAN - echo " Cleaning up" + echo " CLEAN" $(RM) -r $(BUILDPREFIX) endef diff --git a/example/nmake.mk b/example/nmake.mk index b722140..0874154 100644 --- a/example/nmake.mk +++ b/example/nmake.mk @@ -1,24 +1,13 @@ # Makefile for Wirepas C Mesh API example, Microsoft NMAKE version +# Variables + # This example needs the C Mesh API library MESH_LIB_FOLDER = ..\lib MESH_LIB = $(MESH_LIB_FOLDER)\build\mesh_api_lib.lib -# Microsoft Visual studio command line toolchain on Windows -# Use Visual Studio defaults -#CC = cl -#AS = ml - -# Visual Studio C compiler flags -CFLAGS = $(CFLAGS) /nologo /W4 /WX /O2 /MD /TC - -# Linker flags -LDFLAGS = $(LDFLAGS) /nologo - -# Platform flags -!MESSAGE Platform: WIN32 -PLATFORM_IS_WIN32 = 1 -CFLAGS = $(CFLAGS) /DPLATFORM_IS_WIN32=1 +# Detect platform and set toolchain variables +!INCLUDE $(MESH_LIB_FOLDER)\tools_msvc.mk # Path of source files and build outputs SOURCEPREFIX = . @@ -53,7 +42,7 @@ all: app app: lib $(TARGET_APP) clean: - echo Cleaning up + echo CLEAN -del /F $(OBJECTS) $(TARGET_APP) >NUL 2>NUL -rmdir /S /Q $(BUILDPREFIX) >NUL 2>NUL @@ -61,10 +50,11 @@ lib: cd $(MESH_LIB_FOLDER) && $(MAKE) /nologo /f nmake.mk .c.obj: + echo CC $*.c -mkdir $(@D) >NUL 2>NUL $(CC) $(CFLAGS) /c /Fo$@ $*.c $(TARGET_APP): $(OBJECTS) $(MESH_LIB) - echo Linking $@ + echo LINK $@ -mkdir $(@D) >NUL 2>NUL $(CC) $(LDFLAGS) /Fe$@ $** diff --git a/lib/gnu_make.mk b/lib/gnu_make.mk index fb58925..d848bc7 100644 --- a/lib/gnu_make.mk +++ b/lib/gnu_make.mk @@ -3,7 +3,7 @@ # Variables # Detect platform and set toolchain variables -include platform.mk +include tools.mk # Path of source files and build outputs SOURCEPREFIX := . @@ -43,12 +43,12 @@ define COMPILE endef define LINK_LIB - echo " Linking $(1)" + echo " AR $(1)" $(ARCHIVE) $(1) $(2) endef define CLEAN - echo " Cleaning up" + echo " CLEAN" $(RM) -r $(BUILDPREFIX) endef diff --git a/lib/nmake.mk b/lib/nmake.mk index 84d17dd..2e2708d 100644 --- a/lib/nmake.mk +++ b/lib/nmake.mk @@ -2,21 +2,8 @@ # Variables -# Microsoft Visual studio command line toolchain on Windows -# Use Visual Studio defaults -#CC = cl -#AS = ml - -# Visual Studio C compiler flags -CFLAGS = $(CFLAGS) /nologo /W4 /WX /O2 /MD /TC - -# Linker flags -LDFLAGS = $(LDFLAGS) - -# Platform flags -!MESSAGE Platform: WIN32 -PLATFORM_IS_WIN32 = 1 -CFLAGS = $(CFLAGS) /DPLATFORM_IS_WIN32=1 +# Detect platform and set toolchain variables +!INCLUDE tools_msvc.mk # Path of source files and build outputs SOURCEPREFIX = . @@ -60,15 +47,16 @@ all: lib lib: $(TARGET_LIB) clean: - echo Cleaning up + echo CLEAN -del /F $(OBJECTS) $(TARGET_LIB) >NUL 2>NUL -rmdir /S /Q $(BUILDPREFIX) >NUL 2>NUL .c.obj: + echo CC $*.c -mkdir $(@D) >NUL 2>NUL $(CC) $(CFLAGS) /c /Fo$@ $*.c $(TARGET_LIB): $(OBJECTS) - echo Linking $@ + echo LIB $@ -mkdir $(@D) >NUL 2>NUL lib /NOLOGO /OUT:$@ $** diff --git a/lib/platform.mk b/lib/tools.mk similarity index 100% rename from lib/platform.mk rename to lib/tools.mk diff --git a/lib/tools_msvc.mk b/lib/tools_msvc.mk new file mode 100644 index 0000000..a5e0301 --- /dev/null +++ b/lib/tools_msvc.mk @@ -0,0 +1,17 @@ +# Toolchain settings for Wirepas C Mesh API library, Microsoft NMAKE version + +# Microsoft Visual studio command line toolchain on Windows +# Use Visual Studio defaults +#CC = cl +#AS = ml + +# Visual Studio C compiler flags +CFLAGS = $(CFLAGS) /nologo /W4 /WX /O2 /MD /TC + +# Linker flags +LDFLAGS = $(LDFLAGS) /nologo + +# Platform flags +!MESSAGE Platform: WIN32 +PLATFORM_IS_WIN32 = 1 +CFLAGS = $(CFLAGS) /DPLATFORM_IS_WIN32=1 diff --git a/test/gnu_make.mk b/test/gnu_make.mk index 86bfa29..01dff7c 100644 --- a/test/gnu_make.mk +++ b/test/gnu_make.mk @@ -1,11 +1,13 @@ # Makefile for Wirepas C Mesh API test suite, GNU make version +# Variables + # This example needs the C Mesh API library MESH_LIB_FOLDER := ../lib MESH_LIB := $(MESH_LIB_FOLDER)/build/mesh_api_lib.a # Detect platform and set toolchain variables -include $(MESH_LIB_FOLDER)/platform.mk +include $(MESH_LIB_FOLDER)/tools.mk # Path of source files and build outputs SOURCEPREFIX := . @@ -46,12 +48,12 @@ define COMPILE endef define LINK - echo " Linking $(1)" - $(CC) $(CFLAGS) $(LDFLAGS) -o $(1) $(2) $(MESH_LIB) + echo " LD $(1)" + $(CC) $(LDFLAGS) -o $(1) $(2) $(MESH_LIB) endef define CLEAN - echo " Cleaning up" + echo " CLEAN" $(RM) -r $(BUILDPREFIX) endef diff --git a/test/nmake.mk b/test/nmake.mk index 0c1c068..5d71267 100644 --- a/test/nmake.mk +++ b/test/nmake.mk @@ -1,24 +1,13 @@ # Makefile for Wirepas C Mesh API test suite, Microsoft NMAKE version +# Variables + # This example needs the C Mesh API library MESH_LIB_FOLDER = ..\lib MESH_LIB = $(MESH_LIB_FOLDER)\build\mesh_api_lib.lib -# Microsoft Visual studio command line toolchain on Windows -# Use Visual Studio defaults -#CC = cl -#AS = ml - -# Visual Studio C compiler flags -CFLAGS = $(CFLAGS) /nologo /W4 /WX /O2 /MD /TC - -# Linker flags -LDFLAGS = $(LDFLAGS) /nologo - -# Platform flags -!MESSAGE Platform: WIN32 -PLATFORM_IS_WIN32 = 1 -CFLAGS = $(CFLAGS) /DPLATFORM_IS_WIN32=1 +# Detect platform and set toolchain variables +!INCLUDE $(MESH_LIB_FOLDER)\tools_msvc.mk # Path of source files and build outputs SOURCEPREFIX = . @@ -61,7 +50,7 @@ all: app app: lib $(TARGET_APP) clean: - echo Cleaning up + echo CLEAN -del /F $(OBJECTS) $(TARGET_APP) >NUL 2>NUL -rmdir /S /Q $(BUILDPREFIX) >NUL 2>NUL @@ -69,10 +58,11 @@ lib: cd $(MESH_LIB_FOLDER) && $(MAKE) /nologo /f nmake.mk .c.obj: + echo CC $*.c -mkdir $(@D) >NUL 2>NUL $(CC) $(CFLAGS) /c /Fo$@ $*.c $(TARGET_APP): $(OBJECTS) $(MESH_LIB) - echo Linking $@ + echo LINK $@ -mkdir $(@D) >NUL 2>NUL $(CC) $(LDFLAGS) /Fe$@ $**