diff --git a/.gitignore b/.gitignore index 32f420ef469dbd42c3f2877e2aed8e94ce2c1705..a67ff3f5070df7276dc94a9f9f7cfb155098ecd7 100644 --- a/.gitignore +++ b/.gitignore @@ -7,11 +7,14 @@ *.elf *.zip *.d +*.o +*.e *.ihex *.pyc *~ obj_* Makefile.target +Makefile.*.defines tools/doxygen/html patches-* tools/tunslip @@ -19,8 +22,6 @@ tools/tunslip6 build tools/coffee-manager/build/ tools/coffee-manager/coffee.jar -tools/collect-view/build/ -tools/collect-view/dist/ COOJA.testlog # platform build artifacts @@ -31,6 +32,7 @@ COOJA.testlog *.nrf52dk *.openmote-cc2538 *.sky +*.firmware *.srf06-cc26xx *.zoul @@ -50,14 +52,11 @@ COOJA.testlog #test artifacts *.testlog -*.log.prog -*.report -summary +*.scriptlog +*.coojalog *.summary -*.runerr -*.runlog -*.faillog -tests/[0-9][0-9]-*/report +*.err +summary tests/[0-9][0-9]-*/org/ # x86 UEFI files diff --git a/.gitmodules b/.gitmodules index f2cd29451fad845817433d428d1590b090487e89..36eb3cd956acd33b47a2a8fe4fdd391c936e853e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,9 @@ [submodule "tools/cooja"] path = tools/cooja url = https://github.com/contiki-ng/cooja.git +[submodule "os/net/security/tinydtls"] + path = os/net/security/tinydtls + url = https://github.com/contiki-ng/tinydtls.git +[submodule "tests/18-coap-lwm2m/example-lwm2m-standalone"] + path = tests/18-coap-lwm2m/example-lwm2m-standalone + url = https://github.com/contiki-ng/example-lwm2m-standalone.git diff --git a/.travis.yml b/.travis.yml index 16fb5abd3c3d95c372151aad1a9c2c2d236a79ff..00dba89abb2f6e53f2123ee2683864a83e14bb27 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,108 +1,35 @@ -# Workaround for the issue found in the stable image promoted on Dec 1, 2016. -# See https://github.com/travis-ci/travis-ci/issues/6928#issuecomment-264227708 -group: deprecated +# Setup environment for Docker +language: generic +services: docker notifications: - email: false -language: c #NOTE: this will set CC=gcc which might cause trouble -before_script: - - WGET="travis_retry wget --continue --tries=20 --waitretry=10 --retry-connrefused --no-dns-cache --timeout 300" - - sudo apt-get -qq update + - email: false - ## Support building a binary that is identical to the CI - - echo -n "Contiki will be compiled with RELSTR=" ; git --git-dir .git describe --tags --always - - ## Install doxygen - - if [ ${BUILD_CATEGORY:-0} = doxygen ] ; then - sudo add-apt-repository ppa:libreoffice/ppa -y && sudo apt-get -qq update && - sudo apt-get --no-install-suggests --no-install-recommends -qq install doxygen && - doxygen --version ; - fi - - ## Install msp430 toolchain - - sudo apt-get -qq install lib32z1 - - $WGET http://simonduq.github.io/resources/mspgcc-4.7.2-compiled.tar.bz2 && - tar xjf mspgcc*.tar.bz2 -C /tmp/ && - sudo cp -f -r /tmp/msp430/* /usr/local/ && - rm -rf /tmp/msp430 mspgcc*.tar.bz2 && - msp430-gcc --version - - ## Install 32-bit compatibility libraries - - sudo apt-get -qq install libc6:i386 libgcc1:i386 gcc-4.6-base:i386 - libstdc++5:i386 libstdc++6:i386 - - ## Install mainline ARM toolchain and srecord. - - if [ ${BUILD_ARCH:-0} = arm-aapcs ] ; then - sudo apt-get -qq install srecord && - $WGET https://launchpad.net/gcc-arm-embedded/5.0/5-2015-q4-major/+download/gcc-arm-none-eabi-5_2-2015q4-20151219-linux.tar.bz2 && - tar xjf gcc-arm-none-eabi-5_2-2015q4-20151219-linux.tar.bz2 -C /tmp/ && - sudo cp -f -r /tmp/gcc-arm-none-eabi-5_2-2015q4/* /usr/local/ && - rm -rf /tmp/gcc-arm-none-eabi-* gcc-arm-none-eabi-*-linux.tar.bz2 && - arm-none-eabi-gcc --version ; - fi - - ## Install NXP toolchain - - if [ ${BUILD_ARCH:-0} = jn516x ] ; then - $WGET http://simonduq.github.io/resources/ba-elf-gcc-4.7.4-part1.tar.bz2 && - $WGET http://simonduq.github.io/resources/ba-elf-gcc-4.7.4-part2.tar.bz2 && - $WGET http://simonduq.github.io/resources/jn516x-sdk-4163-1416.tar.bz2 && - mkdir /tmp/jn516x-sdk /tmp/ba-elf-gcc && - tar xjf jn516x-sdk-*.tar.bz2 -C /tmp/jn516x-sdk && - tar xjf ba-elf-gcc-*part1.tar.bz2 -C /tmp/ba-elf-gcc && - tar xjf ba-elf-gcc-*part2.tar.bz2 -C /tmp/ba-elf-gcc && - sudo cp -f -r /tmp/jn516x-sdk /usr/ && - sudo cp -f -r /tmp/ba-elf-gcc /usr/ && - export PATH=/usr/ba-elf-gcc/bin:$PATH && - rm -rf /tmp/ba-elf-gcc* /tmp/jn516x-sdk* && - ba-elf-gcc --version ; - fi - - ## Install mainline ARM toolchain and download nRF52 SDK - - if [ ${BUILD_ARCH:-0} = nrf52dk ] ; then - sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa && - sudo apt-get -qq update && - sudo apt-get -qq install gcc-arm-embedded srecord && - arm-none-eabi-gcc --version && - $WGET https://developer.nordicsemi.com/nRF5_IoT_SDK/nRF5_IoT_SDK_v0.9.x/nrf5_iot_sdk_3288530.zip && - mkdir /tmp/nrf52-sdk && - unzip nrf5_iot_sdk_3288530.zip -d /tmp/nrf52-sdk && - export NRF52_SDK_ROOT=/tmp/nrf52-sdk ; - fi - - ## Compile cooja.jar only when it's going to be needed - - if [ ${BUILD_CATEGORY:-0} = sim ] ; then - java -version && - ant -q -f tools/cooja/build.xml jar && - sudo java -Xshare:dump -version ; - fi - -script: - ## tests/Makefile handles most of generic logic - - "make -C tests/??-$BUILD_TYPE RUNALL=true summary" - -after_script: - ## Print cooja test logs - - "[ ${BUILD_CATEGORY:-0} = sim ] && tail tests/??-$BUILD_TYPE/*.testlog" - ## Print a basic summary - - "echo 'Summary:'; cat tests/??-$BUILD_TYPE/summary" - - "FAILS=`grep -c ' FAIL ' tests/??-$BUILD_TYPE/summary`" - ## This will detect whether the build should pass or fail - - "test $FAILS -eq 0; exit $?" +before_install: + # Environment setup before test script + - export CNG_HOST_PATH=`pwd` + - export DOCKER_IMG='simonduq/contiki-ng:latest' + - sudo chgrp -hR 1000 $CNG_HOST_PATH + - docker pull $DOCKER_IMG + - ant -q -f $CNG_HOST_PATH/tools/cooja/build.xml jar +script: # The test script for each build. + - docker run --privileged -v $CNG_HOST_PATH:/home/user/contiki-ng -ti $DOCKER_IMG bash --login -c "make -C tests/??-$TEST_NAME"; + # Check outcome of the test + - $CNG_HOST_PATH/tests/check-test.sh $CNG_HOST_PATH/tests/??-$TEST_NAME; exit $?; env: - ## This magically kick-off parallel jobs for each of the for the sets - ## of environment variable defined below - - BUILD_TYPE='doxygen' BUILD_CATEGORY='doxygen' - - BUILD_TYPE='compile-base' BUILD_CATEGORY='compile' - - BUILD_TYPE='compile-arm-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm-aapcs' - - BUILD_TYPE='compile-nxp-ports' BUILD_CATEGORY='compile' BUILD_ARCH='jn516x' - - BUILD_TYPE='compile-nrf52-ports' BUILD_CATEGORY='compile' BUILD_ARCH='nrf52dk' - - BUILD_TYPE='compile-tools' BUILD_CATEGORY='compile' - - BUILD_TYPE='rpl-lite' BUILD_CATEGORY='sim' - - BUILD_TYPE='rpl-classic' BUILD_CATEGORY='sim' - - BUILD_TYPE='ipv6' BUILD_CATEGORY='sim' - - BUILD_TYPE='nullnet' BUILD_CATEGORY='sim' - - BUILD_TYPE='base' BUILD_CATEGORY='sim' - - BUILD_TYPE='ieee802154' BUILD_CATEGORY='sim' - - BUILD_TYPE='6tisch' BUILD_CATEGORY='sim' + # Parallel builds + - TEST_NAME='compile-base' + - TEST_NAME='compile-arm-ports-01' + - TEST_NAME='compile-arm-ports-02' + - TEST_NAME='rpl-lite' + - TEST_NAME='rpl-classic' + - TEST_NAME='tun-rpl-br' + - TEST_NAME='coap-lwm2m' + - TEST_NAME='simulation-base' + - TEST_NAME='ieee802154' + - TEST_NAME='compile-nxp-ports' + - TEST_NAME='doxygen' + - TEST_NAME='compile-tools' + - TEST_NAME='native-runs' diff --git a/LICENSE.md b/LICENSE.md index c180b146da65b01aceaab9672403acd1470b2d75..b2f909d44b4f1c724248967b44396bcd8ef6d00d 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Contiki is licensed under the 3-clause BSD license. This license gives +Contiki-NG is licensed under the 3-clause BSD license. This license gives everyone the right to use and distribute the code, either in binary or source code format, as long as the copyright license is retained in the source code. diff --git a/Makefile.include b/Makefile.include index 3b8c41605877240ab227dee86d65456cb987942f..dd24fcacbd15486aa16d6e6287bc70df7ff00d8e 100644 --- a/Makefile.include +++ b/Makefile.include @@ -8,7 +8,9 @@ endif # Setting this option is also important for tests on Cooja motes to check for warnings. WERROR ?= 1 -include $(CONTIKI)/Makefile.identify-target +include $(CONTIKI)/Makefile.identify-target + +CONTIKI_NG_TARGET_LIB = contiki-ng-$(TARGET).a ifeq ($(DEFINES),) -include Makefile.$(TARGET).defines @@ -40,9 +42,11 @@ LOWERCASE = -abcdefghijklmnopqrstuvwxyz/ UPPERCASE = _ABCDEFGHIJKLMNOPQRSTUVWXYZ_ TARGET_UPPERCASE := ${strip ${shell echo $(TARGET) | sed y!$(LOWERCASE)!$(UPPERCASE)!}} CFLAGS += -DCONTIKI=1 -DCONTIKI_TARGET_$(TARGET_UPPERCASE)=1 +CFLAGS += -DCONTIKI_TARGET_STRING=\"$(TARGET)\" ifneq ($(BOARD),) TARGET_BOARD_UPPERCASE := ${strip ${shell echo $(BOARD) | sed y!$(LOWERCASE)!$(UPPERCASE)!}} CFLAGS += -DCONTIKI_BOARD_$(TARGET_BOARD_UPPERCASE)=1 +CFLAGS += -DCONTIKI_BOARD_STRING=\"$(BOARD)\" endif MODULES += os os/sys os/dev os/lib os/services @@ -52,12 +56,17 @@ ifneq ("$(wildcard project-conf.h)","") CFLAGS += -DPROJECT_CONF_PATH=\"project-conf.h\" endif -MODULES += os os/net os/net/mac os/storage +MODULES += os os/net os/net/mac os/net/mac/framer os/net/routing os/storage -oname = ${patsubst %.c,%.o,${patsubst %.S,%.o,$(1)}} +define oname +${patsubst %.c,%.o, \ +${patsubst %.S,%.o, \ +${patsubst %.s,%.o, \ +$(1) \ +}}} +endef CONTIKI_OBJECTFILES = ${addprefix $(OBJECTDIR)/,${call oname, $(CONTIKI_SOURCEFILES)}} - PROJECT_OBJECTFILES = ${addprefix $(OBJECTDIR)/,${call oname, $(PROJECT_SOURCEFILES)}} # Provide way to create $(OBJECTDIR) if it has been removed by make clean @@ -80,13 +89,43 @@ else include $(target_makefile) endif +# Decide whether to build or to skip this target for this platform +ifneq ("", "$(PLATFORMS_ONLY)") + ifeq ("","$(filter $(TARGET), $(PLATFORMS_ONLY))") + PLATFORM_ACTION = skip + endif +endif + +ifneq ("", "$(PLATFORMS_EXCLUDE)") + ifneq ("","$(filter $(TARGET), $(PLATFORMS_EXCLUDE))") + PLATFORM_ACTION = skip + endif +endif + +ifneq ($(BOARD),) +ifneq ("", "$(BOARDS_ONLY)") + ifeq ("","$(filter $(BOARD), $(BOARDS_ONLY))") + PLATFORM_ACTION = skip + endif +endif + +ifneq ("", "$(BOARDS_EXCLUDE)") + ifneq ("","$(filter $(BOARD), $(BOARDS_EXCLUDE))") + PLATFORM_ACTION = skip + endif +endif +endif # $(BOARD) not empty + +PLATFORM_ACTION ?= build + # Configure MAC layer # The different options MAKE_MAC_NULLMAC = 0 MAKE_MAC_CSMA = 1 MAKE_MAC_TSCH = 2 -MAKE_MAC_OTHER = 3 +MAKE_MAC_BLE = 3 +MAKE_MAC_OTHER = 4 # Make CSMA the default MAC MAKE_MAC ?= MAKE_MAC_CSMA @@ -106,6 +145,11 @@ ifeq ($(MAKE_MAC),MAKE_MAC_TSCH) CFLAGS += -DMAC_CONF_WITH_TSCH=1 endif +ifeq ($(MAKE_MAC),MAKE_MAC_BLE) + MODULES += os/net/mac/ble + CFLAGS += -DMAC_CONF_WITH_BLE=1 +endif + ifeq ($(MAKE_MAC),MAKE_MAC_OTHER) CFLAGS += -DMAC_CONF_WITH_OTHER=1 endif @@ -140,7 +184,7 @@ ifeq ($(WITH_IP64),1) endif # Configure Routing protocol -MAKE_ROUTING_NONE = 0 +MAKE_ROUTING_NULLROUTING = 0 MAKE_ROUTING_RPL_CLASSIC = 1 MAKE_ROUTING_RPL_LITE = 2 @@ -148,28 +192,36 @@ MAKE_ROUTING_RPL_LITE = 2 ifeq ($(MAKE_NET),MAKE_NET_IPV6) MAKE_ROUTING ?= MAKE_ROUTING_RPL_LITE else -MAKE_ROUTING ?= MAKE_ROUTING_NONE +MAKE_ROUTING ?= MAKE_ROUTING_NULLROUTING endif ifeq ($(MAKE_ROUTING),MAKE_ROUTING_RPL_CLASSIC) - CFLAGS += -DUIP_CONF_IPV6_RPL=1 - CFLAGS += -DUIP_CONF_IPV6_RPL_CLASSIC=1 - MODULES += os/net/rpl-classic + CFLAGS += -DROUTING_CONF_RPL_CLASSIC=1 + MODULES += os/net/routing/rpl-classic else ifeq ($(MAKE_ROUTING),MAKE_ROUTING_RPL_LITE) - CFLAGS += -DUIP_CONF_IPV6_RPL=1 - CFLAGS += -DUIP_CONF_IPV6_RPL_LITE=1 - MODULES += os/net/rpl-lite -else - CFLAGS += -DUIP_CONF_IPV6_RPL=0 + CFLAGS += -DROUTING_CONF_RPL_LITE=1 + MODULES += os/net/routing/rpl-lite +else ifeq ($(MAKE_ROUTING),MAKE_ROUTING_NULLROUTING) + CFLAGS += -DROUTING_CONF_NULLROUTING=1 + MODULES += os/net/routing/nullrouting endif -ifdef MODULES - UNIQUEMODULES = $(call uniq,$(MODULES)) - MODULEDIRS = ${wildcard ${addprefix $(CONTIKI)/, $(UNIQUEMODULES)}} - MODULES_SOURCES = ${foreach d, $(MODULEDIRS), ${subst ${d}/,,${wildcard $(d)/*.c}}} - MODULES_INCLUDES = ${wildcard ${foreach d, $(MODULEDIRS), $(d)/Makefile.${notdir $(d)}}} - include $(MODULES_INCLUDES) - CONTIKI_SOURCEFILES += $(MODULES_SOURCES) +MODULEDIRS = $(MODULES_REL) ${wildcard ${addprefix $(CONTIKI)/, $(MODULES)}} +UNIQUEMODULES = $(call uniq,$(MODULEDIRS)) +MODULES_SOURCES = ${foreach d, $(MODULEDIRS), ${subst ${d}/,,${wildcard $(d)/*.c}}} +CONTIKI_SOURCEFILES += $(MODULES_SOURCES) + +# Include module-specific makefiles +MODULES_INCLUDES = ${wildcard ${foreach d, $(MODULEDIRS), $(d)/Makefile.${notdir $(d)}}} +include $(MODULES_INCLUDES) +# Iterate once more: include the modules added from the previous include. +# Only works with one level of nested module inclusion. +include $(MODULES_INCLUDES) + +# C-include module-specific macros using -imacros +MODULES_IMACROS = ${wildcard ${foreach d, $(MODULEDIRS), $(d)/module-macros.h}} +ifneq ($(MODULES_IMACROS),) + CFLAGS += ${foreach d, $(MODULES_IMACROS), -imacros $(d)} endif ### Verbosity control. Use make V=1 to get verbose builds. @@ -206,13 +258,15 @@ SOURCEDIRS = . $(PROJECTDIRS) $(CONTIKI_TARGET_DIRS_CONCAT) $(CONTIKI_ARCH_DIRS) vpath %.c $(SOURCEDIRS) vpath %.S $(SOURCEDIRS) +vpath %.s $(SOURCEDIRS) CFLAGS += ${addprefix -I,$(SOURCEDIRS) $(CONTIKI)} ### Check for a git repo and pass version if found ### git.exe in Windows cmd shells may require no stderr redirection ifndef RELSTR -RELSTR:=${shell git --git-dir ${CONTIKI}/.git describe --tags --always --dirty} +RELSTR:=${shell git --git-dir ${CONTIKI}/.git --work-tree ${CONTIKI} describe \ + --tags --always --dirty} endif ifneq ($(RELSTR),) @@ -237,26 +291,26 @@ sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ rm -f $(@:.o=.$$$$) endef +### Harmonize filename of a .map file, if the platform's build system wants +### to create one +CONTIKI_NG_PROJECT_MAP = $(addsuffix -$(TARGET).map, $(basename $@)) + +.PHONY: clean distclean usage help targets boards savetarget savedefines viewconf + clean: - -rm -f *~ *core core *.srec \ - *.lst *.map \ - *.cprg *.bin *.data contiki*.a *.firmware core-labels.S *.ihex *.ini \ - *.ce *.co - rm -rf $(CLEAN) + -rm -f *.d *.e *.o $(CONTIKI_NG_TARGET_LIB) $(CLEAN) -rm -rf $(OBJECTDIR) + -rm -f $(addsuffix -$(TARGET).map, $(CONTIKI_PROJECT)) + -rm -f $(addsuffix .$(TARGET), $(CONTIKI_PROJECT)) -distclean: clean - -rm -f ${addsuffix .$(TARGET),$(CONTIKI_PROJECT)} +distclean: + @for TARG in `ls $(CONTIKI)/arch/platform $(TARGETDIRS)`; do \ + echo make $$TARG clean; \ + make TARGET=$$TARG clean; \ + done -include $(CONTIKI)/arch/platform/$(TARGET)/Makefile.customrules-$(TARGET) -ifndef CUSTOM_RULE_C_TO_CE -%.ce: %.c - $(TRACE_CC) - $(Q)$(CC) $(CFLAGS) -DAUTOSTART_ENABLE -c $< -o $@ - $(STRIP) --strip-unneeded -g -x $@ -endif - ifndef CUSTOM_RULE_C_TO_OBJECTDIR_O $(OBJECTDIR)/%.o: %.c | $(OBJECTDIR) $(TRACE_CC) @@ -268,6 +322,9 @@ ifndef CUSTOM_RULE_S_TO_OBJECTDIR_O $(OBJECTDIR)/%.o: %.S | $(OBJECTDIR) $(TRACE_AS) $(Q)$(AS) $(ASFLAGS) -o $@ $< +$(OBJECTDIR)/%.o: %.s | $(OBJECTDIR) + $(TRACE_AS) + $(Q)$(AS) $(ASFLAGS) -o $@ $< endif ifndef CUSTOM_RULE_C_TO_OBJECTDIR_S @@ -300,18 +357,12 @@ ifndef CUSTOM_RULE_C_TO_E $(Q)$(CC) $(CFLAGS) -E $< -o $@ endif -ifndef CUSTOM_RULE_C_TO_CO -%.co: %.c - $(TRACE_CC) - $(Q)$(CC) $(CFLAGS) -DAUTOSTART_ENABLE -c $< -o $@ -endif - ifndef AROPTS AROPTS = rcf endif ifndef CUSTOM_RULE_ALLOBJS_TO_TARGETLIB -contiki-$(TARGET).a: $(CONTIKI_OBJECTFILES) +$(CONTIKI_NG_TARGET_LIB): $(CONTIKI_OBJECTFILES) $(TRACE_AR) $(Q)$(AR) $(AROPTS) $@ $^ endif @@ -321,7 +372,7 @@ ifndef LD endif ifndef CUSTOM_RULE_LINK -%.$(TARGET): %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a +%.$(TARGET): %.o $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) $(CONTIKI_NG_TARGET_LIB) $(TRACE_LD) $(Q)$(LD) $(LDFLAGS) $(TARGET_STARTFILES) ${filter-out %.a,$^} \ ${filter %.a,$^} $(TARGET_LIBFILES) -o $@ @@ -334,7 +385,25 @@ endif $(NM) -S -td --size-sort $< | grep -i " [t] " | cut -d' ' -f2,4 usage: - @echo "make MAKETARGETS... [TARGET=(TARGET)] [BOARD=(BOARD)] [savetarget] [targets]" + @echo "Usage:" + @echo " make [TARGET=(TARGET)] [BOARD=(BOARD)] [DEFINES=(DEFINES)] [target]" + @echo "" + @echo "Typical usage:" + @echo " make [TARGET=(TARGET)] [BOARD=(BOARD)] [all]" + @echo "" + @echo " Will build Contiki-NG firmware(s) from the current example dir" + @echo " for platform TARGET, board BOARD." + @echo "" + @echo "Miscellaneous targets:" + @echo " targets Prints list of supported platforms" + @echo " boards Prints a list of supported boards for TARGET" + @echo " savegtarget Saves TARGET and BOARD for future invocations of make" + @echo " savedefines Saves DEFINES for future invocations of make" + @echo " clean Removes all compiled files for TARGET" + @echo " distclean Removes all compiled files for all TARGETs" + @echo " viewconf Prints Contiki-NG build configuration for TARGET" + +help: usage targets: @ls $(CONTIKI)/arch/platform $(TARGETDIRS) @@ -366,6 +435,9 @@ viewconf: @echo "##### \"MAKE_MAC\": ______________________________ $(MAKE_MAC)" @echo "##### \"MAKE_NET\": ______________________________ $(MAKE_NET)" @echo "##### \"MAKE_ROUTING\": __________________________ $(MAKE_ROUTING)" +ifdef MAKE_COAP_DTLS_KEYSTORE + @echo "##### \"MAKE_COAP_DTLS_KEYSTORE\": _______________ $(MAKE_COAP_DTLS_KEYSTORE)" +endif @echo "----------------- C variables: -----------------" $(Q)$(CC) $(CFLAGS) -E $(CONTIKI)/tools/viewconf.c | grep \#\#\#\#\# @echo "------------------------------------------------" @@ -384,8 +456,15 @@ viewconf: # the match-anything rule below instead. %: %.c +ifeq ($(PLATFORM_ACTION),skip) +# Skip this target. +$(CONTIKI_PROJECT): + @echo "Skipping $@: not for the '$(TARGET)/$(BOARD)' platform!" +else +# Build this target. # Match-anything pattern rule to allow the project makefiles to # abstract from the actual binary name. It needs to contain some # command in order to be a rule, not just a prerequisite. %: %.$(TARGET) @ +endif diff --git a/README.md b/README.md index 86dadeb75f93d20ceb6b2dbeacb4761f98320152..df7d7ff58a12ce9c56df246a183c06e7cd6f576c 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,25 @@ -# Contiki-NG: the Next Generation Contiki +# Contiki-NG: The OS for Next Generation IoT Devices [](https://travis-ci.org/contiki-ng/contiki-ng/branches) +[](https://github.com/contiki-ng/contiki-ng/blob/master/LICENSE.md) +[](https://github.com/contiki-ng/contiki-ng/releases/latest) +[](https://github.com/contiki-ng/contiki-ng/releases/latest) +[](https://github.com/contiki-ng/contiki-ng/commit/HEAD) + +Contiki-NG is an open-source, cross-platform operating system for Next-Generation IoT devices. It focuses on dependable (secure and reliable) low-power communication and standard protocols, such as IPv6/6LoWPAN, 6TiSCH, RPL, and CoAP. Contiki-NG comes with extensive documentation, tutorials, a roadmap, release cycle, and well-defined development flow for smooth integration of community contributions. + +Unless excplicitly stated otherwise, Contiki-NG sources are distributed under +the terms of the [3-clause BSD license](LICENSE.md). + +Contiki-NG started as a fork of the Contiki OS and retains some of its original features. + +Find out more: -Contiki-NG is a fork of Contiki, with focus on next generation IoT protocols and platforms. -Important links: * GitHub repository: https://github.com/contiki-ng/contiki-ng * Documentation: https://github.com/contiki-ng/contiki-ng/wiki +* Web site: http://contiki-ng.org + +Engage with the community: + * Gitter: https://gitter.im/contiki-ng * Twitter: https://twitter.com/contiki_ng -* Web site: http://contiki-ng.org diff --git a/arch/cpu/arm/Makefile.arm b/arch/cpu/arm/Makefile.arm new file mode 100644 index 0000000000000000000000000000000000000000..0b26624235e445d581b7aef263d018bd380e224f --- /dev/null +++ b/arch/cpu/arm/Makefile.arm @@ -0,0 +1,54 @@ +CC = arm-none-eabi-gcc +CPP = arm-none-eabi-cpp +LD = arm-none-eabi-gcc +AR = arm-none-eabi-ar +OBJCOPY = arm-none-eabi-objcopy +OBJDUMP = arm-none-eabi-objdump +NM = arm-none-eabi-nm +SIZE = arm-none-eabi-size +SREC_CAT = srec_cat + +CFLAGS += -mthumb -mabi=aapcs -mlittle-endian +CFLAGS += -Werror -Wall +CFLAGS += -std=c99 +CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing +CFLAGS += -fshort-enums -fomit-frame-pointer -fno-builtin + +LDFLAGS += -mthumb -mlittle-endian + +OBJDUMP_FLAGS += --disassemble --source --disassembler-options=force-thumb + +### Are we building with code size optimisations? +SMALL ?= 1 +ifeq ($(SMALL),1) + CFLAGS += -Os +else + CFLAGS += -O2 +endif + +### Use CMSIS and the existing dbg-io from arch/cpu/arm/common +CONTIKI_ARM_DIRS += . common/dbg-io +CONTIKI_CPU_DIRS += $(addprefix ../arm/, $(CONTIKI_ARM_DIRS)) + +### CPU-dependent cleanup files +CLEAN += *.elf *.bin *.lst *.hex *.i16hex + +### Don't treat the following files as intermediate +.PRECIOUS: %.elf %.hex %.bin + +%.i16hex: %.elf + $(OBJCOPY) -O ihex $< $@ + +%.hex: %.i16hex + $(SREC_CAT) $< -intel -o $@ -intel + +%.bin: %.elf + $(OBJCOPY) -O binary $(OBJCOPY_FLAGS) $< $@ + +%.lst: %.elf + $(OBJDUMP) $(OBJDUMP_FLAGS) $< > $@ + +### We don't really need the .hex and .bin for the .$(TARGET) but let's make +### sure they get built +%.$(TARGET): %.elf %.hex %.bin + cp $< $@ diff --git a/arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.h b/arch/cpu/arm/arm-def.h similarity index 62% rename from arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.h rename to arch/cpu/arm/arm-def.h index 1a993d3be4ada62f914d25d11cfec3993eeceaf6..92b19048dfe1ffcc9cd1c25646f70d7adf538a46 100644 --- a/arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.h +++ b/arch/cpu/arm/arm-def.h @@ -1,10 +1,11 @@ /* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright @@ -29,43 +30,56 @@ */ /*---------------------------------------------------------------------------*/ /** - * \addtogroup cc26xx - * @{ - * - * \defgroup cc26xx-gpio-interrupts CC13xx/CC26xx GPIO interrupt handling - * - * The CC13xx/CC26xx GPIO interrupt handler and an API which can be used by - * other parts of the code when they wish to be notified of a GPIO interrupt - * + * \addtogroup arm * @{ * * \file - * Header file for the CC13xx/CC26xx GPIO interrupt management + * Compiler and data type definitions for all ARM-based CPUs */ /*---------------------------------------------------------------------------*/ -#ifndef GPIO_INTERRUPT_H_ -#define GPIO_INTERRUPT_H_ +#ifndef ARM_DEF_ +#define ARM_DEF_ /*---------------------------------------------------------------------------*/ #include <stdint.h> /*---------------------------------------------------------------------------*/ -typedef void (*gpio_interrupt_handler_t)(uint8_t ioid); -/*---------------------------------------------------------------------------*/ -/** \brief Initialise the GPIO interrupt handling module */ -void gpio_interrupt_init(void); - /** - * \brief Register a GPIO interrupt handler - * \param f Pointer to a handler to be called when an interrupt is raised on - * ioid - * \param ioid Associate \a f with this ioid. \e ioid must be specified with - * its numeric representation (0, 1, .. 31). Defines for these - * numeric representations are IOID_x + * \name Macros and typedefs + * + * Those values are not meant to be modified by the user + * @{ */ -void gpio_interrupt_register_handler(uint8_t ioid, gpio_interrupt_handler_t f); +#define CLOCK_CONF_SECOND 128 -#endif /* GPIO_INTERRUPT_H_ */ -/*---------------------------------------------------------------------------*/ -/** - * @} - * @} +/* Clock (time) comparison macro */ +#define CLOCK_LT(a, b) ((signed long)((a) - (b)) < 0) + +/* Platform typedefs */ +typedef uint32_t clock_time_t; +typedef uint32_t uip_stats_t; + +typedef uint32_t rtimer_clock_t; +#define RTIMER_CLOCK_DIFF(a, b) ((int32_t)((a) - (b))) +/** @} */ + +/* + * The stdio.h that ships with the arm-gcc toolchain does this: + * + * int _EXFUN(putchar, (int)); + * [...] + * #define putchar(x) putc(x, stdout) + * + * This causes us a lot of trouble: For platforms using this toolchain, every + * time we use putchar we need to first #undef putchar. What we do here is to + * #undef putchar across the board. The resulting code will cause the linker + * to search for a symbol named putchar and this allows us to use the + * implementation under os/lib/dbg-io. + * + * This will fail if stdio.h is included before contiki.h, but it is common + * practice to include contiki.h first */ +#include <stdio.h> +#undef putchar +/*---------------------------------------------------------------------------*/ +#endif /* ARM_DEF_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/arch/cpu/arm/arm.txt b/arch/cpu/arm/arm.txt deleted file mode 100644 index 5264866629fbe990a39b5b3532bb2b6e04fe4297..0000000000000000000000000000000000000000 --- a/arch/cpu/arm/arm.txt +++ /dev/null @@ -1,19 +0,0 @@ -/** - * \defgroup cmsis CMSIS (Cortex Microcontroller Software Interface Standard) - * \ingroup arm - */ - -/** - * \defgroup aducrf101 ADUCRF101 - * \ingroup arm - */ - -/** - * \defgroup at91sam7s AT91SAM7S - * \ingroup arm - */ - -/** - * \defgroup stm32f103 STM32F103 - * \ingroup arm - */ diff --git a/arch/cpu/arm/common/SD-card/cfs-sdcard.c b/arch/cpu/arm/common/SD-card/cfs-sdcard.c index 9be29fd2e50bb788a3999c48e9c5c36bba81cec1..4c44e3e6b393e07fb435b452cf0faa5babdab8fa 100644 --- a/arch/cpu/arm/common/SD-card/cfs-sdcard.c +++ b/arch/cpu/arm/common/SD-card/cfs-sdcard.c @@ -1,7 +1,6 @@ #include <efs-sdcard.h> #include <sys/process.h> #include <cfs/cfs.h> -#include <debug-uart.h> #include <stdio.h> diff --git a/arch/cpu/arm/common/dbg-io/dbg-printf.c b/arch/cpu/arm/common/dbg-io/dbg-printf.c deleted file mode 100644 index 9bd09c1ac03d1f175e54850403ce50404fe0b5a2..0000000000000000000000000000000000000000 --- a/arch/cpu/arm/common/dbg-io/dbg-printf.c +++ /dev/null @@ -1,30 +0,0 @@ -#include <stdio.h> -#include <debug-uart.h> -#include <string.h> -#include <strformat.h> - -static StrFormatResult -write_str(void *user_data, const char *data, unsigned int len) -{ - if (len > 0) dbg_send_bytes((unsigned char*)data, len); - return STRFORMAT_OK; -} - - -static StrFormatContext ctxt = - { - write_str, - NULL - }; -int -printf(const char *fmt, ...) -{ - int res; - va_list ap; - va_start(ap, fmt); - res = format_str_v(&ctxt, fmt, ap); - va_end(ap); - return res; -} - - diff --git a/arch/cpu/arm/common/dbg-io/dbg-putchar.c b/arch/cpu/arm/common/dbg-io/dbg-putchar.c deleted file mode 100644 index 54f3db53fcb53de26dc006e350b818a5dbd6fa5e..0000000000000000000000000000000000000000 --- a/arch/cpu/arm/common/dbg-io/dbg-putchar.c +++ /dev/null @@ -1,26 +0,0 @@ -#include <stdio.h> -#include <debug-uart.h> -#include <string.h> - -#undef putchar -#undef putc - -int -putchar(int c) -{ - dbg_putchar(c); - return c; -} - -int -putc(int c, FILE *f) -{ - dbg_putchar(c); - return c; -} - -int -__sp(struct _reent *_ptr, int c, FILE *_p) { - dbg_putchar(c); - return c; -} diff --git a/arch/cpu/arm/common/dbg-io/dbg-puts.c b/arch/cpu/arm/common/dbg-io/dbg-puts.c deleted file mode 100644 index fa90d10226d864464431277e86d93d875dc13c3f..0000000000000000000000000000000000000000 --- a/arch/cpu/arm/common/dbg-io/dbg-puts.c +++ /dev/null @@ -1,11 +0,0 @@ -#include <stdio.h> -#include <debug-uart.h> -#include <string.h> - -int -puts(const char *str) -{ - dbg_send_bytes((unsigned char*)str, strlen(str)); - dbg_putchar('\n'); - return 0; -} diff --git a/arch/cpu/arm/common/dbg-io/dbg-snprintf.c b/arch/cpu/arm/common/dbg-io/dbg-snprintf.c deleted file mode 100644 index 230d6891a94eaa54b94b8646206cca5e70f4402c..0000000000000000000000000000000000000000 --- a/arch/cpu/arm/common/dbg-io/dbg-snprintf.c +++ /dev/null @@ -1,48 +0,0 @@ -#include <stdio.h> -#include <strformat.h> -#include <string.h> - -struct FmtBuffer -{ - char *pos; - size_t left; -}; - -static StrFormatResult -buffer_str(void *user_data, const char *data, unsigned int len) -{ - struct FmtBuffer *buffer = (struct FmtBuffer*)user_data; - if (len >= buffer->left) { - len = buffer->left; - len--; - } - - memcpy(buffer->pos, data, len); - buffer->pos += len; - buffer->left -= len; - return STRFORMAT_OK; -} - -int snprintf(char *str, size_t size, const char *format, ...) -{ - int res; - va_list ap; - va_start(ap, format); - res = vsnprintf(str, size, format, ap); - va_end(ap); - return res; -} - -int vsnprintf(char *str, size_t size, const char *format, va_list ap) -{ - struct FmtBuffer buffer; - StrFormatContext ctxt; - int res; - ctxt.write_str = buffer_str; - ctxt.user_data = &buffer; - buffer.pos = str; - buffer.left = size; - res = format_str_v(&ctxt, format, ap); - *buffer.pos = '\0'; - return res; -} diff --git a/arch/cpu/arm/common/dbg-io/dbg-sprintf.c b/arch/cpu/arm/common/dbg-io/dbg-sprintf.c deleted file mode 100644 index 8124fc3637a432ffd991b8b9bf29c780f9ce5f04..0000000000000000000000000000000000000000 --- a/arch/cpu/arm/common/dbg-io/dbg-sprintf.c +++ /dev/null @@ -1,26 +0,0 @@ -#include <stdio.h> -#include <strformat.h> -#include <string.h> - -static StrFormatResult -buffer_str(void *user_data, const char *data, unsigned int len) -{ - memcpy(*(char**)user_data, data, len); - (*(char**)user_data) += len; - return STRFORMAT_OK; -} - -int -sprintf(char *str, const char *format, ...) -{ - StrFormatContext ctxt; - int res; - va_list ap; - va_start(ap, format); - ctxt.write_str = buffer_str; - ctxt.user_data = &str; - res = format_str_v(&ctxt, format, ap); - *str = '\0'; - va_end(ap); - return res; -} diff --git a/arch/cpu/arm/common/dbg-io/strformat.c b/arch/cpu/arm/common/dbg-io/strformat.c deleted file mode 100644 index 13b91a56336bb0990fedf2319799ec5c4924243a..0000000000000000000000000000000000000000 --- a/arch/cpu/arm/common/dbg-io/strformat.c +++ /dev/null @@ -1,617 +0,0 @@ -#include <strformat.h> - -#define HAVE_DOUBLE - -#define HAVE_LONGLONG -#ifndef LARGEST_SIGNED -#ifdef HAVE_LONGLONG -#define LARGEST_SIGNED long long int -#else -#define LARGEST_UNSIGNED long int -#endif -#endif - -#ifndef LARGEST_UNSIGNED -#ifdef HAVE_LONGLONG -#define LARGEST_UNSIGNED unsigned long long int -#else -#define LARGEST_UNSIGNED unsigned long int -#endif -#endif - -#ifndef POINTER_INT -#define POINTER_INT unsigned long -#endif - -typedef unsigned int FormatFlags; - -#define MAKE_MASK(shift,size) (((1 << size) - 1) << (shift)) - -#define JUSTIFY_SHIFT 0 -#define JUSTIFY_SIZE 1 -#define JUSTIFY_RIGHT 0x0000 -#define JUSTIFY_LEFT 0x0001 -#define JUSTIFY_MASK MAKE_MASK(JUSTIFY_SHIFT,JUSTIFY_SIZE) - - -/* How a positive number is prefixed */ -#define POSITIVE_SHIFT (JUSTIFY_SHIFT + JUSTIFY_SIZE) -#define POSITIVE_NONE (0x0000 << POSITIVE_SHIFT) -#define POSITIVE_SPACE (0x0001 << POSITIVE_SHIFT) -#define POSITIVE_PLUS (0x0003 << POSITIVE_SHIFT) -#define POSITIVE_MASK MAKE_MASK(POSITIVE_SHIFT, POSITIVE_SIZE) - -#define POSITIVE_SIZE 2 - -#define ALTERNATE_FORM_SHIFT (POSITIVE_SHIFT + POSITIVE_SIZE) -#define ALTERNATE_FORM_SIZE 1 -#define ALTERNATE_FORM (0x0001 << ALTERNATE_FORM_SHIFT) - - -#define PAD_SHIFT (ALTERNATE_FORM_SHIFT + ALTERNATE_FORM_SIZE) -#define PAD_SIZE 1 -#define PAD_SPACE (0x0000 << PAD_SHIFT) -#define PAD_ZERO (0x0001 << PAD_SHIFT) - -#define SIZE_SHIFT (PAD_SHIFT + PAD_SIZE) -#define SIZE_SIZE 3 -#define SIZE_CHAR (0x0001 << SIZE_SHIFT) -#define SIZE_SHORT (0x0002 << SIZE_SHIFT) -#define SIZE_INT (0x0000 << SIZE_SHIFT) -#define SIZE_LONG (0x0003 << SIZE_SHIFT) -#define SIZE_LONGLONG (0x0004 << SIZE_SHIFT) -#define SIZE_MASK MAKE_MASK(SIZE_SHIFT,SIZE_SIZE) - -#define CONV_SHIFT (SIZE_SHIFT + SIZE_SIZE) -#define CONV_SIZE 3 -#define CONV_INTEGER (0x0001 << CONV_SHIFT) -#define CONV_FLOAT (0x0002 << CONV_SHIFT) -#define CONV_POINTER (0x0003 << CONV_SHIFT) -#define CONV_STRING (0x0004 << CONV_SHIFT) -#define CONV_CHAR (0x0005 << CONV_SHIFT) -#define CONV_PERCENT (0x0006 << CONV_SHIFT) -#define CONV_WRITTEN (0x0007 << CONV_SHIFT) -#define CONV_MASK MAKE_MASK(CONV_SHIFT, CONV_SIZE) - -#define RADIX_SHIFT (CONV_SHIFT + CONV_SIZE) -#define RADIX_SIZE 2 -#define RADIX_DECIMAL (0x0001 << RADIX_SHIFT) -#define RADIX_OCTAL (0x0002 << RADIX_SHIFT) -#define RADIX_HEX (0x0003 << RADIX_SHIFT) -#define RADIX_MASK MAKE_MASK(RADIX_SHIFT,RADIX_SIZE) - -#define SIGNED_SHIFT (RADIX_SHIFT + RADIX_SIZE) -#define SIGNED_SIZE 1 -#define SIGNED_NO (0x0000 << SIGNED_SHIFT) -#define SIGNED_YES (0x0001 << SIGNED_SHIFT) -#define SIGNED_MASK MAKE_MASK(SIGNED_SHIFT,SIGNED_SIZE) - -#define CAPS_SHIFT (SIGNED_SHIFT + SIGNED_SIZE) -#define CAPS_SIZE 1 -#define CAPS_NO (0x0000 << CAPS_SHIFT) -#define CAPS_YES (0x0001 << CAPS_SHIFT) -#define CAPS_MASK MAKE_MASK(CAPS_SHIFT,CAPS_SIZE) - -#define FLOAT_SHIFT (CAPS_SHIFT + CAPS_SIZE) -#define FLOAT_SIZE 2 -#define FLOAT_NORMAL (0x0000 << FLOAT_SHIFT) -#define FLOAT_EXPONENT (0x0001 << FLOAT_SHIFT) -#define FLOAT_DEPENDANT (0x0002 << FLOAT_SHIFT) -#define FLOAT_HEX (0x0003 << FLOAT_SHIFT) -#define FLOAT_MASK MAKE_MASK(FLOAT_SHIFT, FLOAT_SIZE) - -static FormatFlags -parse_flags(const char **posp) -{ - FormatFlags flags = 0; - const char *pos = *posp; - while (1) { - switch(*pos) { - case '-': - flags |= JUSTIFY_LEFT; - break; - case '+': - flags |= POSITIVE_PLUS; - break; - case ' ': - flags |= POSITIVE_SPACE; - break; - case '#': - flags |= ALTERNATE_FORM; - break; - case '0': - flags |= PAD_ZERO; - break; - default: - *posp = pos; - return flags; - } - pos++; - } - -} - -static unsigned int -parse_uint(const char **posp) -{ - unsigned v = 0; - const char *pos = *posp; - char ch; - while((ch = *pos) >= '0' && ch <= '9') { - v = v * 10 + (ch - '0'); - pos++; - } - *posp = pos; - return v; -} - -#define MAXCHARS_HEX ((sizeof(LARGEST_UNSIGNED) * 8) / 4 ) - -/* Largest number of characters needed for converting an unsigned integer. - */ -#define MAXCHARS ((sizeof(LARGEST_UNSIGNED) * 8 + 2) / 3 ) - -static unsigned int -output_uint_decimal(char **posp, LARGEST_UNSIGNED v) -{ - unsigned int len; - char *pos = *posp; - while (v > 0) { - *--pos = (v % 10) + '0'; - v /= 10; - } - len = *posp - pos; - *posp = pos; - return len; -} - -static unsigned int -output_uint_hex(char **posp, LARGEST_UNSIGNED v, unsigned int flags) -{ - unsigned int len; - const char *hex = (flags & CAPS_YES) ?"0123456789ABCDEF":"0123456789abcdef"; - char *pos = *posp; - while (v > 0) { - *--pos = hex[(v % 16)]; - v /= 16; - } - len = *posp - pos; - *posp = pos; - return len; -} - -static unsigned int -output_uint_octal(char **posp, LARGEST_UNSIGNED v) -{ - unsigned int len; - char *pos = *posp; - while (v > 0) { - *--pos = (v % 8) + '0'; - v /= 8; - } - len = *posp - pos; - *posp = pos; - return len; -} - -static StrFormatResult -fill_space(const StrFormatContext *ctxt, unsigned int len) -{ - StrFormatResult res; - static const char buffer[16] = " "; - while(len > 16) { - res = ctxt->write_str(ctxt->user_data, buffer, 16); - if (res != STRFORMAT_OK) return res; - len -= 16; - } - if (len == 0) return STRFORMAT_OK; - return ctxt->write_str(ctxt->user_data, buffer, len); -} - -static StrFormatResult -fill_zero(const StrFormatContext *ctxt, unsigned int len) -{ - StrFormatResult res; - static const char buffer[16] = "0000000000000000"; - while(len > 16) { - res = ctxt->write_str(ctxt->user_data, buffer, 16); - if (res != STRFORMAT_OK) return res; - len -= 16; - } - if (len == 0) return STRFORMAT_OK; - return ctxt->write_str(ctxt->user_data, buffer, len); -} - -#define CHECKCB(res) {if ((res) != STRFORMAT_OK) {va_end(ap); return -1;}} - -int -format_str(const StrFormatContext *ctxt, const char *format, ...) -{ - int ret; - va_list ap; - va_start(ap, format); - ret = format_str_v(ctxt, format, ap); - va_end(ap); - return ret; -} - -int -format_str_v(const StrFormatContext *ctxt, const char *format, va_list ap) -{ - unsigned int written = 0; - const char *pos = format; - while(*pos != '\0') { - FormatFlags flags; - unsigned int minwidth = 0; - int precision = -1; /* Negative means no precision */ - char ch; - const char *start = pos; - while( (ch = *pos) != '\0' && ch != '%') pos++; - if (pos != start) { - CHECKCB(ctxt->write_str(ctxt->user_data, start, pos - start)); - written += pos - start; - } - if (*pos == '\0') { - va_end(ap); - return written; - } - pos++; - if (*pos == '\0') { - va_end(ap); - return written; - } - flags = parse_flags(&pos); - - /* parse width */ - if (*pos >= '1' && *pos <= '9') { - minwidth = parse_uint(&pos); - } else if (*pos == '*') { - int w = va_arg(ap,int); - if (w < 0) { - flags |= JUSTIFY_LEFT; - minwidth = w; - } else { - minwidth = w; - } - pos ++; - } - - /* parse precision */ - if (*pos == '.') { - pos++; - if (*pos >= '0' && *pos <= '9') { - precision = parse_uint(&pos); - } else if (*pos == '*') { - pos++; - precision = va_arg(ap,int); - } - } - if (*pos == 'l') { - pos++; - if (*pos == 'l') { - flags |= SIZE_LONGLONG; - pos++; - } else { - flags |= SIZE_LONG; - } - } else if (*pos == 'h') { - pos++; - if (*pos == 'h') { - flags |= SIZE_CHAR; - pos++; - } else { - flags |= SIZE_SHORT; - } - } - - /* parse conversion specifier */ - switch(*pos) { - case 'd': - case 'i': - flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_YES; - break; - case 'u': - flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_NO; - break; - case 'o': - flags |= CONV_INTEGER | RADIX_OCTAL | SIGNED_NO; - break; - case 'x': - flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO; - break; - case 'X': - flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO | CAPS_YES; - break; -#ifdef HAVE_DOUBLE - case 'f': - flags |= CONV_FLOAT | FLOAT_NORMAL; - break; - case 'F': - flags |= CONV_FLOAT | FLOAT_NORMAL | CAPS_YES; - break; - case 'e': - flags |= CONV_FLOAT | FLOAT_EXPONENT; - break; - case 'E': - flags |= CONV_FLOAT | FLOAT_EXPONENT | CAPS_YES; - break; - case 'g': - flags |= CONV_FLOAT | FLOAT_DEPENDANT; - break; - case 'G': - flags |= CONV_FLOAT | FLOAT_DEPENDANT | CAPS_YES; - break; - case 'a': - flags |= CONV_FLOAT | FLOAT_HEX; - break; - case 'A': - flags |= CONV_FLOAT | FLOAT_HEX | CAPS_YES; - break; -#endif - case 'c': - flags |= CONV_CHAR; - break; - case 's': - flags |= CONV_STRING; - break; - case 'p': - flags |= CONV_POINTER; - break; - case 'n': - flags |= CONV_WRITTEN; - break; - case '%': - flags |= CONV_PERCENT; - break; - case '\0': - va_end(ap); - return written; - } - pos++; - switch(flags & CONV_MASK) { - case CONV_PERCENT: - CHECKCB(ctxt->write_str(ctxt->user_data, "%", 1)); - written++; - break; - case CONV_INTEGER: - { - /* unsigned integers */ - char *prefix = 0; /* sign, "0x" or "0X" */ - unsigned int prefix_len = 0; - char buffer[MAXCHARS]; - char *conv_pos = buffer + MAXCHARS; - unsigned int conv_len = 0; - unsigned int width = 0; - unsigned int precision_fill; - unsigned int field_fill; - LARGEST_UNSIGNED uvalue = 0; - int negative = 0; - - if (precision < 0) precision = 1; - else flags &= ~PAD_ZERO; - - if (flags & SIGNED_YES) { - /* signed integers */ - LARGEST_SIGNED value = 0; - switch(flags & SIZE_MASK) { - case SIZE_CHAR: - value = (signed char)va_arg(ap, int); - break; - case SIZE_SHORT: - value = (short)va_arg(ap, int); - break; - case SIZE_INT: - value = va_arg(ap, int); - break; -#ifndef HAVE_LONGLONG - case SIZE_LONGLONG: /* Treat long long the same as long */ -#endif - case SIZE_LONG: - value = va_arg(ap, long); - break; -#ifdef HAVE_LONGLONG - case SIZE_LONGLONG: - value = va_arg(ap, long long); - break; -#endif - } - if (value < 0) { - uvalue = -value; - negative = 1; - } else { - uvalue = value; - } - } else { - - switch(flags & SIZE_MASK) { - case SIZE_CHAR: - uvalue = (unsigned char)va_arg(ap,unsigned int); - break; - case SIZE_SHORT: - uvalue = (unsigned short)va_arg(ap,unsigned int); - break; - case SIZE_INT: - uvalue = va_arg(ap,unsigned int); - break; -#ifndef HAVE_LONGLONG - case SIZE_LONGLONG: /* Treat long long the same as long */ -#endif - case SIZE_LONG: - uvalue = va_arg(ap,unsigned long); - break; -#ifdef HAVE_LONGLONG - case SIZE_LONGLONG: - uvalue = va_arg(ap,unsigned long long); - break; -#endif - } - } - - switch(flags & (RADIX_MASK)) { - case RADIX_DECIMAL: - conv_len = output_uint_decimal(&conv_pos,uvalue); - break; - case RADIX_OCTAL: - conv_len = output_uint_octal(&conv_pos,uvalue); - break; - case RADIX_HEX: - conv_len = output_uint_hex(&conv_pos,uvalue, flags); - break; - } - - width += conv_len; - precision_fill = (precision > conv_len) ? precision - conv_len : 0; - if ((flags & (RADIX_MASK | ALTERNATE_FORM)) - == (RADIX_OCTAL | ALTERNATE_FORM)) { - if (precision_fill < 1) precision_fill = 1; - } - - width += precision_fill; - - if ((flags & (RADIX_MASK | ALTERNATE_FORM)) - == (RADIX_HEX | ALTERNATE_FORM) && uvalue != 0) { - prefix_len = 2; - if (flags & CAPS_YES) { - prefix = "0X"; - } else { - prefix = "0x"; - } - } - - if (flags & SIGNED_YES) { - if (negative) { - prefix = "-"; - prefix_len = 1; - } else { - switch(flags & POSITIVE_MASK) { - case POSITIVE_SPACE: - prefix = " "; - prefix_len = 1; - break; - case POSITIVE_PLUS: - prefix = "+"; - prefix_len = 1; - break; - } - } - } - - width += prefix_len; - - field_fill = (minwidth > width) ? minwidth - width : 0; - - if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) { - if (flags & PAD_ZERO) { - precision_fill += field_fill; - field_fill = 0; /* Do not double count padding */ - } else { - CHECKCB(fill_space(ctxt,field_fill)); - } - } - - if (prefix_len > 0) - CHECKCB(ctxt->write_str(ctxt->user_data, prefix, prefix_len)); - written += prefix_len; - - CHECKCB(fill_zero(ctxt,precision_fill)); - written += precision_fill; - - CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos,conv_len)); - written += conv_len; - - if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) { - CHECKCB(fill_space(ctxt,field_fill)); - } - written += field_fill; - } - break; - case CONV_STRING: - { - unsigned int field_fill; - unsigned int len; - char *str = va_arg(ap,char *); - if (str) { - char *pos = str; - while(*pos != '\0') pos++; - len = pos - str; - } else { - str = "(null)"; - len = 6; - } - if (precision >= 0 && precision < len) len = precision; - field_fill = (minwidth > len) ? minwidth - len : 0; - if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) { - CHECKCB(fill_space(ctxt,field_fill)); - } - CHECKCB(ctxt->write_str(ctxt->user_data, str,len)); - written += len; - if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) { - CHECKCB(fill_space(ctxt,field_fill)); - } - written += field_fill; - } - break; - case CONV_POINTER: - { - LARGEST_UNSIGNED uvalue = - (LARGEST_UNSIGNED)(POINTER_INT)va_arg(ap,void *); - char buffer[MAXCHARS_HEX + 3]; - char *conv_pos = buffer + MAXCHARS_HEX+3; - unsigned int conv_len; - unsigned int field_fill; - - conv_len = output_uint_hex(&conv_pos,uvalue,flags); - if (conv_len == 0) { - *--conv_pos = '0'; - conv_len++; - } - *--conv_pos = 'x'; - *--conv_pos = '0'; - *--conv_pos = '#'; - conv_len += 3; - - field_fill = (minwidth > conv_len) ? minwidth - conv_len : 0; - - if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) { - CHECKCB(fill_space(ctxt,field_fill)); - } - - CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos,conv_len)); - written += conv_len; - - if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) { - CHECKCB(fill_space(ctxt,field_fill)); - } - written += field_fill; - } - break; - case CONV_CHAR: - { - char ch = va_arg(ap,int); - unsigned int field_fill = (minwidth > 1) ? minwidth - 1 : 0; - if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) { - CHECKCB(fill_space(ctxt,field_fill)); - written += field_fill; - } - - CHECKCB(ctxt->write_str(ctxt->user_data, &ch, 1)); - written++; - - if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) { - CHECKCB(fill_space(ctxt,field_fill)); - } - written+= field_fill; - } - break; - case CONV_WRITTEN: - { - int *p = va_arg(ap,int*); - *p = written; - } - break; - - } - } - - return written; -} diff --git a/arch/cpu/arm/common/dbg-io/strformat.h b/arch/cpu/arm/common/dbg-io/strformat.h deleted file mode 100644 index c32eed67014c784cfce253b266b76b0e81429f9c..0000000000000000000000000000000000000000 --- a/arch/cpu/arm/common/dbg-io/strformat.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef STRFORMAT_H_ -#define STRFORMAT_H_ - -#include <stdarg.h> - -#define STRFORMAT_OK 0 -#define STRFORMAT_FAILED 1 -typedef unsigned int StrFormatResult; - -/* The data argument may only be considered valid during the function call */ -typedef StrFormatResult (*StrFormatWrite)(void *user_data, const char *data, unsigned int len); - -typedef struct _StrFormatContext -{ - StrFormatWrite write_str; - void *user_data; -} StrFormatContext; - -int format_str(const StrFormatContext *ctxt, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2,3))); - -int -format_str_v(const StrFormatContext *ctxt, const char *format, va_list ap); - -#endif /* STRFORMAT_H_ */ diff --git a/arch/cpu/arm/common/sys/mtarch.c b/arch/cpu/arm/common/sys/mtarch.c deleted file mode 100644 index 6bf011411a7a0acc94d41e5b1d2f43ec4a66c26b..0000000000000000000000000000000000000000 --- a/arch/cpu/arm/common/sys/mtarch.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (c) 2016, Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \addtogroup arm-cm-mtarch - * @{ - * - * \file - * Implmentation of the ARM Cortex-M support for Contiki multi-threading. - */ -#include CMSIS_DEV_HDR -#include "sys/mt.h" - -#include <stdint.h> - -#define EXC_RETURN_PROCESS_THREAD_BASIC_FRAME 0xfffffffd - -/* Check whether EXC_RETURN[3:0] in LR indicates a preempted process thread. */ -#if __ARM_ARCH == 7 -#define PREEMPTED_PROCESS_THREAD() \ - "and r0, lr, #0xf\n\t" \ - "cmp r0, #0xd\n\t" -#elif __ARM_ARCH == 6 -#define PREEMPTED_PROCESS_THREAD() \ - "mov r0, lr\n\t" \ - "movs r1, #0xf\n\t" \ - "and r0, r1\n\t" \ - "cmp r0, #0xd\n\t" -#else -#error Unsupported ARM architecture -#endif -/*----------------------------------------------------------------------------*/ -/** - * \brief SVCall system handler - * - * This exception handler executes the action requested by the corresponding - * \c svc instruction, which is a task switch from the main Contiki thread to an - * mt thread or the other way around. - */ -__attribute__ ((__naked__)) -void -svcall_handler(void) -{ - /* - * Decide whether to switch to the main thread or to a process thread, - * depending on the type of the thread preempted by SVCall. - */ - __asm__ (PREEMPTED_PROCESS_THREAD() -#if __ARM_ARCH == 7 - "it eq\n\t" -#endif - "beq switch_to_main_thread\n\t" - - /* - * - Retrieve from the main stack the PSP passed to SVCall through R0. Note - * that it cannot be retrieved directly from R0 on exception entry because - * this register may have been overwritten by other exceptions on SVCall - * entry. - * - Save the main thread context to the main stack. - * - Restore the process thread context from the process stack. - * - Return to Thread mode, resuming the process thread. - */ -#if __ARM_ARCH == 7 - "ldr r0, [sp]\n\t" - "push {r4-r11, lr}\n\t" - "add r1, r0, #9 * 4\n\t" - "msr psp, r1\n\t" - "ldmia r0, {r4-r11, pc}"); -#elif __ARM_ARCH == 6 - "mov r0, r8\n\t" - "mov r1, r9\n\t" - "mov r2, r10\n\t" - "mov r3, r11\n\t" - "push {r0-r7, lr}\n\t" - "ldr r0, [sp, #9 * 4]\n\t" - "ldmia r0!, {r4-r7}\n\t" - "mov r8, r4\n\t" - "mov r9, r5\n\t" - "mov r10, r6\n\t" - "mov r11, r7\n\t" - "ldmia r0!, {r3-r7}\n\t" - "msr psp, r0\n\t" - "bx r3"); -#endif -} -/*----------------------------------------------------------------------------*/ -/** - * \brief PendSV system handler - * - * This exception handler executes following a call to mtarch_pstart() from - * another exception handler. It performs a task switch to the main Contiki - * thread if it is not already running. - */ -__attribute__ ((__naked__)) -void -pendsv_handler(void) -{ - /* - * Return without doing anything if PendSV has not preempted a process thread. - * This can occur either because PendSV has preempted the main thread, in - * which case there is nothing to do, or because mtarch_pstart() has been - * called from an exception handler without having called mt_init() first, in - * which case PendSV may have preempted an exception handler and nothing must - * be done because mt is not active. - */ - __asm__ ( PREEMPTED_PROCESS_THREAD() -#if __ARM_ARCH == 7 - "it ne\n\t" - "bxne lr\n" -#elif __ARM_ARCH == 6 - "beq switch_to_main_thread\n\t" - "bx lr\n" -#endif - - /* - * - Save the process thread context to the process stack. - * - Place into the main stack the updated PSP that SVCall must return through - * R0. - * - Restore the main thread context from the main stack. - * - Return to Thread mode, resuming the main thread. - */ - "switch_to_main_thread:\n\t" - "mrs r0, psp\n\t" -#if __ARM_ARCH == 7 - "stmdb r0!, {r4-r11, lr}\n\t" - "str r0, [sp, #9 * 4]\n\t" - "pop {r4-r11, pc}"); -#elif __ARM_ARCH == 6 - "mov r3, lr\n\t" - "sub r0, #5 * 4\n\t" - "stmia r0!, {r3-r7}\n\t" - "mov r4, r8\n\t" - "mov r5, r9\n\t" - "sub r0, #9 * 4\n\t" - "mov r6, r10\n\t" - "mov r7, r11\n\t" - "stmia r0!, {r4-r7}\n\t" - "pop {r4-r7}\n\t" - "sub r0, #4 * 4\n\t" - "mov r8, r4\n\t" - "mov r9, r5\n\t" - "str r0, [sp, #5 * 4]\n\t" - "mov r10, r6\n\t" - "mov r11, r7\n\t" - "pop {r4-r7, pc}"); -#endif -} -/*----------------------------------------------------------------------------*/ -void -mtarch_init(void) -{ - SCB->CCR = (SCB->CCR -#ifdef SCB_CCR_NONBASETHRDENA_Msk - /* - * Make sure that any attempt to enter Thread mode with exceptions - * active faults. - * - * Only SVCall and PendSV are allowed to forcibly enter Thread - * mode, and they are configured with the same, lowest exception - * priority, so no other exceptions may be active. - */ - & ~SCB_CCR_NONBASETHRDENA_Msk -#endif - /* - * Force 8-byte stack pointer alignment on exception entry in order - * to be able to use AAPCS-conforming functions as exception - * handlers. - */ - ) | SCB_CCR_STKALIGN_Msk; - - /* - * Configure SVCall and PendSV with the same, lowest exception priority. - * - * This makes sure that they cannot preempt each other, and that the processor - * executes them after having handled all other exceptions. If both are - * pending at the same time, then SVCall takes precedence because of its lower - * exception number. In addition, the associated exception handlers do not - * have to check whether they are returning to Thread mode, because they - * cannot preempt any other exception. - */ - NVIC_SetPriority(SVCall_IRQn, (1 << __NVIC_PRIO_BITS) - 1); - NVIC_SetPriority(PendSV_IRQn, (1 << __NVIC_PRIO_BITS) - 1); - - /* - * Force the preceding configurations to take effect before further - * operations. - */ - __DSB(); - __ISB(); -} -/*----------------------------------------------------------------------------*/ -void -mtarch_start(struct mtarch_thread *thread, - void (*function)(void *data), void *data) -{ - struct mtarch_thread_context *context = &thread->start_stack.context; - - /* - * Initialize the thread context with the appropriate values to call - * function() with data and to make function() return to mt_exit() without - * having to call it explicitly. - */ - context->exc_return = EXC_RETURN_PROCESS_THREAD_BASIC_FRAME; - context->r0 = (uint32_t)data; - context->lr = (uint32_t)mt_exit; - context->pc = (uint32_t)function; - context->xpsr = xPSR_T_Msk; - thread->psp = (uint32_t)context; -} -/*----------------------------------------------------------------------------*/ -void -mtarch_exec(struct mtarch_thread *thread) -{ - /* Pass the PSP to SVCall, and get the updated PSP as its return value. */ - register uint32_t psp __asm__ ("r0") = thread->psp; - __asm__ volatile ("svc #0" - : "+r" (psp) - :: "memory"); - thread->psp = psp; -} -/*----------------------------------------------------------------------------*/ -__attribute__ ((__naked__)) -void -mtarch_yield(void) -{ - /* Invoke SVCall. */ - __asm__ ("svc #0\n\t" - "bx lr"); -} -/*----------------------------------------------------------------------------*/ -void -mtarch_stop(struct mtarch_thread *thread) -{ -} -/*----------------------------------------------------------------------------*/ -void -mtarch_pstart(void) -{ - /* Trigger PendSV. */ - SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; -} -/*----------------------------------------------------------------------------*/ -void -mtarch_pstop(void) -{ -} -/*----------------------------------------------------------------------------*/ -void -mtarch_remove(void) -{ -} -/*----------------------------------------------------------------------------*/ - -/** @} */ diff --git a/arch/cpu/arm/common/sys/mtarch.h b/arch/cpu/arm/common/sys/mtarch.h deleted file mode 100644 index d483e6e3f2516e65e50e49e95c0a685324e7471b..0000000000000000000000000000000000000000 --- a/arch/cpu/arm/common/sys/mtarch.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2016, Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \addtogroup arm - * @{ - * - * \defgroup arm-cm-mtarch ARM Cortex-M support for Contiki multi-threading - * - * All the Cortex-M devices supported by CMSIS-CORE are supported. - * - * An exception handler can decide to make the main Contiki thread preempt any - * running mt thread by calling mtarch_pstart() (e.g. to perform urgent - * operations that have been triggered by some event or that had been - * scheduled). If the running thread is already the main Contiki thread, then - * nothing happens. The corresponding task switch takes place when leaving - * Handler mode. The main Contiki thread then resumes after the call to - * mt_exec() that yielded to the preempted mt thread. - * @{ - * - * \file - * Header file for the ARM Cortex-M support for Contiki multi-threading. - */ -#ifndef MTARCH_H_ -#define MTARCH_H_ - -#include "contiki.h" -#include "sys/cc.h" - -#include <stdint.h> - -#ifndef MTARCH_CONF_STACKSIZE -/** Thread stack size configuration, expressed as a number of 32-bit words. */ -#define MTARCH_CONF_STACKSIZE 256 -#endif -/** Actual stack size, with minimum size and alignment requirements enforced. */ -#define MTARCH_STACKSIZE ((MAX(MTARCH_CONF_STACKSIZE, \ - sizeof(struct mtarch_thread_context) / \ - sizeof(uint32_t)) + 1) & ~1) - -/** - * Structure of a saved thread context. - * - * <tt>xpsr..r0</tt> are managed by the processor (except in mtarch_start()), - * while the other register values are handled by the software. - */ -struct mtarch_thread_context { -#if __ARM_ARCH == 7 - uint32_t r4; - uint32_t r5; - uint32_t r6; - uint32_t r7; -#endif - uint32_t r8; - uint32_t r9; - uint32_t r10; - uint32_t r11; - uint32_t exc_return; -#if __ARM_ARCH == 6 - uint32_t r4; - uint32_t r5; - uint32_t r6; - uint32_t r7; -#endif - uint32_t r0; - uint32_t r1; - uint32_t r2; - uint32_t r3; - uint32_t r12; - uint32_t lr; - uint32_t pc; - uint32_t xpsr; -}; - -struct mtarch_thread { - uint32_t psp; - union { - struct { - uint32_t free[MTARCH_STACKSIZE - - sizeof(struct mtarch_thread_context) / sizeof(uint32_t)]; - struct mtarch_thread_context context; - } start_stack; - uint32_t stack[MTARCH_STACKSIZE]; - } CC_ALIGN(8); -}; - -#endif /* MTARCH_H_ */ - -/** - * @} - * @} - */ diff --git a/arch/cpu/arm/common/usb/Makefile.usb b/arch/cpu/arm/common/usb/Makefile.usb index 3286ca36509fe6c458d76c106c22793880f7637b..05266cf7b77c0031a64b16ec9dd77e8a8d4d7a74 100644 --- a/arch/cpu/arm/common/usb/Makefile.usb +++ b/arch/cpu/arm/common/usb/Makefile.usb @@ -6,7 +6,7 @@ endif STRUCTGEN = structgen -PROJECTDIRS += $(BUILTSRCDIR) +MODULES_REL += $(BUILTSRCDIR) USB_STRING_DESCRIPTORS ?= $(CONTIKI_CPU_ARM)/common/usb/cdc-acm/string-descriptors.xml diff --git a/arch/cpu/arm/common/usb/cdc-acm/cdc-acm-descriptors.c b/arch/cpu/arm/common/usb/cdc-acm/cdc-acm-descriptors.c index 4e9902297eaa42c1249c7776c7b36466949ac3f4..696f2e455337eb32dead54ab4507d7c25111b65d 100644 --- a/arch/cpu/arm/common/usb/cdc-acm/cdc-acm-descriptors.c +++ b/arch/cpu/arm/common/usb/cdc-acm/cdc-acm-descriptors.c @@ -122,5 +122,5 @@ const struct configuration_st { }; -const struct usb_st_configuration_descriptor const *configuration_head = -(struct usb_st_configuration_descriptor const*)&configuration_block; +const struct usb_st_configuration_descriptor* const configuration_head = +(const struct usb_st_configuration_descriptor*)&configuration_block; diff --git a/arch/cpu/arm/common/usb/descriptors.h b/arch/cpu/arm/common/usb/descriptors.h index f5418439570fa53c67ef77bdfac7ac85c82aeea6..6c89f3c038c868d6a704e4a2c676cc7d430468be 100644 --- a/arch/cpu/arm/common/usb/descriptors.h +++ b/arch/cpu/arm/common/usb/descriptors.h @@ -6,5 +6,5 @@ #endif extern const struct usb_st_device_descriptor device_descriptor; -extern const struct usb_st_configuration_descriptor const *configuration_head; +extern const struct usb_st_configuration_descriptor* const configuration_head; #endif /* DESCRIPTORS_H_RPFUB8O7OV__ */ diff --git a/arch/cpu/arm/common/CMSIS/cmsis_armcc.h b/arch/cpu/arm/cortex-m/CMSIS/cmsis_armcc.h similarity index 100% rename from arch/cpu/arm/common/CMSIS/cmsis_armcc.h rename to arch/cpu/arm/cortex-m/CMSIS/cmsis_armcc.h diff --git a/arch/cpu/arm/common/CMSIS/cmsis_armcc_V6.h b/arch/cpu/arm/cortex-m/CMSIS/cmsis_armcc_V6.h similarity index 100% rename from arch/cpu/arm/common/CMSIS/cmsis_armcc_V6.h rename to arch/cpu/arm/cortex-m/CMSIS/cmsis_armcc_V6.h diff --git a/arch/cpu/arm/common/CMSIS/cmsis_gcc.h b/arch/cpu/arm/cortex-m/CMSIS/cmsis_gcc.h similarity index 100% rename from arch/cpu/arm/common/CMSIS/cmsis_gcc.h rename to arch/cpu/arm/cortex-m/CMSIS/cmsis_gcc.h diff --git a/arch/cpu/arm/common/CMSIS/core_cm0.h b/arch/cpu/arm/cortex-m/CMSIS/core_cm0.h similarity index 100% rename from arch/cpu/arm/common/CMSIS/core_cm0.h rename to arch/cpu/arm/cortex-m/CMSIS/core_cm0.h diff --git a/arch/cpu/arm/common/CMSIS/core_cm0plus.h b/arch/cpu/arm/cortex-m/CMSIS/core_cm0plus.h similarity index 99% rename from arch/cpu/arm/common/CMSIS/core_cm0plus.h rename to arch/cpu/arm/cortex-m/CMSIS/core_cm0plus.h index ee5eec184c5ca7807a883d309119f3840a81ab03..773eec6eed2eacf4dc539b6b21cc2807f29271f7 100644 --- a/arch/cpu/arm/common/CMSIS/core_cm0plus.h +++ b/arch/cpu/arm/cortex-m/CMSIS/core_cm0plus.h @@ -66,7 +66,7 @@ * CMSIS definitions ******************************************************************************/ /** - \ingroup Cortex-M0+ + \ingroup Cortex_M0_plus @{ */ diff --git a/arch/cpu/arm/common/CMSIS/core_cm3.h b/arch/cpu/arm/cortex-m/CMSIS/core_cm3.h similarity index 100% rename from arch/cpu/arm/common/CMSIS/core_cm3.h rename to arch/cpu/arm/cortex-m/CMSIS/core_cm3.h diff --git a/arch/cpu/arm/common/CMSIS/core_cm4.h b/arch/cpu/arm/cortex-m/CMSIS/core_cm4.h similarity index 100% rename from arch/cpu/arm/common/CMSIS/core_cm4.h rename to arch/cpu/arm/cortex-m/CMSIS/core_cm4.h diff --git a/arch/cpu/arm/common/CMSIS/core_cm7.h b/arch/cpu/arm/cortex-m/CMSIS/core_cm7.h similarity index 100% rename from arch/cpu/arm/common/CMSIS/core_cm7.h rename to arch/cpu/arm/cortex-m/CMSIS/core_cm7.h diff --git a/arch/cpu/arm/common/CMSIS/core_cmFunc.h b/arch/cpu/arm/cortex-m/CMSIS/core_cmFunc.h similarity index 100% rename from arch/cpu/arm/common/CMSIS/core_cmFunc.h rename to arch/cpu/arm/cortex-m/CMSIS/core_cmFunc.h diff --git a/arch/cpu/arm/common/CMSIS/core_cmInstr.h b/arch/cpu/arm/cortex-m/CMSIS/core_cmInstr.h similarity index 100% rename from arch/cpu/arm/common/CMSIS/core_cmInstr.h rename to arch/cpu/arm/cortex-m/CMSIS/core_cmInstr.h diff --git a/arch/cpu/arm/common/CMSIS/core_cmSimd.h b/arch/cpu/arm/cortex-m/CMSIS/core_cmSimd.h similarity index 100% rename from arch/cpu/arm/common/CMSIS/core_cmSimd.h rename to arch/cpu/arm/cortex-m/CMSIS/core_cmSimd.h diff --git a/arch/cpu/arm/common/CMSIS/core_sc000.h b/arch/cpu/arm/cortex-m/CMSIS/core_sc000.h similarity index 100% rename from arch/cpu/arm/common/CMSIS/core_sc000.h rename to arch/cpu/arm/cortex-m/CMSIS/core_sc000.h diff --git a/arch/cpu/arm/common/CMSIS/core_sc300.h b/arch/cpu/arm/cortex-m/CMSIS/core_sc300.h similarity index 100% rename from arch/cpu/arm/common/CMSIS/core_sc300.h rename to arch/cpu/arm/cortex-m/CMSIS/core_sc300.h diff --git a/arch/cpu/arm/common/CMSIS/core.txt b/arch/cpu/arm/cortex-m/CMSIS/doxygen-group.txt similarity index 84% rename from arch/cpu/arm/common/CMSIS/core.txt rename to arch/cpu/arm/cortex-m/CMSIS/doxygen-group.txt index 1426a8a6af33a3f0b4d9ddc376b31e05f99fe266..4b4bdd0eb3c115f87d33c88b1fcdeb998550994e 100644 --- a/arch/cpu/arm/common/CMSIS/core.txt +++ b/arch/cpu/arm/cortex-m/CMSIS/doxygen-group.txt @@ -1,3 +1,8 @@ +/** + * \defgroup cmsis CMSIS (Cortex Microcontroller Software Interface Standard) + * \ingroup arm + */ + /** * \addtogroup CMSIS_Core_FunctionInterface * \ingroup cmsis @@ -39,7 +44,7 @@ */ /** - * \defgroup Cortex-M0+ Cortex-M0+ + * \defgroup Cortex_M0_plus Cortex-M0+ * \ingroup cmsis */ diff --git a/arch/cpu/arm/cortex-m/Makefile.cortex-m b/arch/cpu/arm/cortex-m/Makefile.cortex-m new file mode 100644 index 0000000000000000000000000000000000000000..444df05cd2307bcd36987c45ab58f81c4bd45fcf --- /dev/null +++ b/arch/cpu/arm/cortex-m/Makefile.cortex-m @@ -0,0 +1,3 @@ +CONTIKI_ARM_DIRS += cortex-m cortex-m/CMSIS + +include $(CONTIKI)/arch/cpu/arm/Makefile.arm diff --git a/arch/cpu/arm/cortex-m/cm3/Makefile.cm3 b/arch/cpu/arm/cortex-m/cm3/Makefile.cm3 new file mode 100644 index 0000000000000000000000000000000000000000..f5e8d2a3ccf18200cbc8a43f75cce65033a042fa --- /dev/null +++ b/arch/cpu/arm/cortex-m/cm3/Makefile.cm3 @@ -0,0 +1,26 @@ +CONTIKI_ARM_DIRS += cortex-m/cm3 + +CFLAGS += -mcpu=cortex-m3 + +LDFLAGS += -mcpu=cortex-m3 -nostartfiles +LDFLAGS += -T $(LDSCRIPT) +LDFLAGS += -Wl,--gc-sections,--sort-section=alignment +LDFLAGS += -Wl,-Map=$(CONTIKI_NG_PROJECT_MAP),--cref,--no-warn-mismatch + +OBJCOPY_FLAGS += --gap-fill 0xff + +### Build syscalls for newlib +MODULES += os/lib/newlib + +CPU_STARTFILES = ${addprefix $(OBJECTDIR)/,${call oname, $(CPU_START_SOURCEFILES)}} + +### Compilation rules +CUSTOM_RULE_LINK = 1 + +.SECONDEXPANSION: + +%.elf: $(CPU_STARTFILES) $$(CONTIKI_OBJECTFILES) %.o $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) $(LDSCRIPT) + $(TRACE_LD) + $(Q)$(LD) $(LDFLAGS) ${filter-out $(LDSCRIPT) %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -lm -o $@ + +include $(CONTIKI)/arch/cpu/arm/cortex-m/Makefile.cortex-m diff --git a/arch/cpu/cc26xx-cc13xx/debug-uart.h b/arch/cpu/arm/cortex-m/cm3/cm3-def.h similarity index 83% rename from arch/cpu/cc26xx-cc13xx/debug-uart.h rename to arch/cpu/arm/cortex-m/cm3/cm3-def.h index c2d9b0ffb81629a9b19511cf36547e06fb01c1f9..041bb3d71e4f0b80201de270b8f7b77a98615ed1 100644 --- a/arch/cpu/cc26xx-cc13xx/debug-uart.h +++ b/arch/cpu/arm/cortex-m/cm3/cm3-def.h @@ -1,16 +1,16 @@ /* - * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. @@ -30,20 +30,24 @@ */ /*---------------------------------------------------------------------------*/ /** - * \addtogroup cc26xx-char-io + * \addtogroup arm + * @{ + * + * \defgroup cm3 Arm Cortex-M3 * @{ * * \file - * This file is here because DBG I/O expects it to be. It just includes - * our own dbg.h which has a non-misleading name and which also adheres - * to Contiki's naming convention + * Compiler and data type definitions for all CM3-based CPUs */ /*---------------------------------------------------------------------------*/ -#ifndef DEBUG_UART_H_ -#define DEBUG_UART_H_ +#ifndef CM3_DEF_H_ +#define CM3_DEF_H_ /*---------------------------------------------------------------------------*/ -#include "dbg.h" +#include "arm-def.h" /*---------------------------------------------------------------------------*/ -#endif /* DEBUG_UART_H_ */ +#endif /* CM3_DEF_H_ */ /*---------------------------------------------------------------------------*/ -/** @} */ +/** + * @} + * @} + */ diff --git a/arch/cpu/arm/cortex-m/cm4/Makefile.cm4 b/arch/cpu/arm/cortex-m/cm4/Makefile.cm4 new file mode 100644 index 0000000000000000000000000000000000000000..1f3cdd00b69a95b67ba873145604e4f10ba9479b --- /dev/null +++ b/arch/cpu/arm/cortex-m/cm4/Makefile.cm4 @@ -0,0 +1,13 @@ +CONTIKI_ARM_DIRS += cortex-m/cm4 + +CFLAGS += -mcpu=cortex-m4 +LDFLAGS += -mcpu=cortex-m4 + +### Compilation rules +CUSTOM_RULE_LINK=1 + +%.elf: $(TARGET_STARTFILES) %.o $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) $(CONTIKI_NG_TARGET_LIB) $(TARGET_LIBS) + $(TRACE_LD) + $(Q)$(CC) $(LDFLAGS) ${filter %.o %.a,$^} -o $@ + +include $(CONTIKI)/arch/cpu/arm/cortex-m/Makefile.cortex-m diff --git a/arch/platform/srf06-cc26xx/launchpad/launchpad-sensors.c b/arch/cpu/arm/cortex-m/cm4/cm4-def.h similarity index 83% rename from arch/platform/srf06-cc26xx/launchpad/launchpad-sensors.c rename to arch/cpu/arm/cortex-m/cm4/cm4-def.h index c940ec68cf061f789dc0f1ac3f661fcc845d3f6e..1144d979802ac37b1be1d04694c92e7cc37322a9 100644 --- a/arch/platform/srf06-cc26xx/launchpad/launchpad-sensors.c +++ b/arch/cpu/arm/cortex-m/cm4/cm4-def.h @@ -1,10 +1,11 @@ /* - * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright @@ -29,19 +30,24 @@ */ /*---------------------------------------------------------------------------*/ /** - * \addtogroup launchpad-peripherals + * \addtogroup arm + * @{ + * + * \defgroup cm4 Arm Cortex-M4 * @{ * * \file - * Generic module controlling LaunchPad sensors + * Compiler and data type definitions for all CM4-based CPUs */ /*---------------------------------------------------------------------------*/ -#include "contiki.h" -#include "launchpad/button-sensor.h" - -#include <string.h> +#ifndef CM4_DEF_H_ +#define CM4_DEF_H_ /*---------------------------------------------------------------------------*/ -/** \brief Exports a global symbol to be used by the sensor API */ -SENSORS(&button_left_sensor, &button_right_sensor); +#include "arm-def.h" /*---------------------------------------------------------------------------*/ -/** @} */ +#endif /* CM4_DEF_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/examples/slip-radio/sky/target-conf.h b/arch/cpu/arm/cortex-m/memory-barrier-cortex.h similarity index 86% rename from examples/slip-radio/sky/target-conf.h rename to arch/cpu/arm/cortex-m/memory-barrier-cortex.h index 08fa665124ee81f62d714395643a69cf54c0aa46..ae0177cf1d761754f19332b755683d6e62c78276 100644 --- a/examples/slip-radio/sky/target-conf.h +++ b/arch/cpu/arm/cortex-m/memory-barrier-cortex.h @@ -29,15 +29,16 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -#ifndef TARGET_CONF_H_ -#define TARGET_CONF_H_ +#ifndef MEMORY_BARRIER_CORTEX_H_ +#define MEMORY_BARRIER_CORTEX_H_ /*---------------------------------------------------------------------------*/ -#define QUEUEBUF_CONF_NUM 4 -#define UIP_CONF_BUFFER_SIZE 140 +#include "contiki.h" -#define CMD_CONF_HANDLERS slip_radio_cmd_handler,cmd_handler_cc2420 -#define SLIP_RADIO_CONF_SENSORS slip_radio_sky_sensors -#define UART1_CONF_RX_WITH_DMA 1 +#ifdef CMSIS_CONF_HEADER_PATH +#include CMSIS_CONF_HEADER_PATH +#endif /*---------------------------------------------------------------------------*/ -#endif /* TARGET_CONF_H_ */ +#define memory_barrier() __DMB() +/*---------------------------------------------------------------------------*/ +#endif /* MEMORY_BARRIER_CORTEX_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/arch/platform/openmote-cc2538/dev/button-sensor.h b/arch/cpu/arm/cortex-m/mutex-cortex.h similarity index 70% rename from arch/platform/openmote-cc2538/dev/button-sensor.h rename to arch/cpu/arm/cortex-m/mutex-cortex.h index 9a08634aec58e9840ba436949836e2715a435aaa..562a0528c9eae3bfd3fdb19f3a4e977f10417572 100644 --- a/arch/platform/openmote-cc2538/dev/button-sensor.h +++ b/arch/cpu/arm/cortex-m/mutex-cortex.h @@ -1,16 +1,16 @@ /* - * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. @@ -27,48 +27,56 @@ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * */ /*---------------------------------------------------------------------------*/ /** - * \addtogroup openmote-cc2538 - * @{ - * - * \defgroup openmote-button-sensor OpenMote-CC2538 user button driver + * \addtogroup arm * - * The user button will generate a sensors_changed event on press as - * well as on release. + * Arm Cortex-M implementation of mutexes using the LDREX, STREX and DMB + * instructions. * * @{ - * - * \file - * Header for the OpenMote-CC2538 button driver */ /*---------------------------------------------------------------------------*/ -#ifndef BUTTON_SENSOR_H_ -#define BUTTON_SENSOR_H_ +#ifndef MUTEX_CORTEX_H_ +#define MUTEX_CORTEX_H_ /*---------------------------------------------------------------------------*/ -#include "lib/sensors.h" -/*---------------------------------------------------------------------------*/ -#define BUTTON_SENSOR "Button" +#include "contiki.h" + +#ifdef CMSIS_CONF_HEADER_PATH +#include CMSIS_CONF_HEADER_PATH +#endif -extern const struct sensors_sensor button_sensor; +#include <stdint.h> +#include <stdbool.h> /*---------------------------------------------------------------------------*/ -extern process_event_t button_press_duration_exceeded; +#define mutex_try_lock(m) mutex_cortex_try_lock(m) +#define mutex_unlock(m) mutex_cortex_unlock(m) /*---------------------------------------------------------------------------*/ -#define BUTTON_SENSOR_CONFIG_TYPE_INTERVAL 0x0100 +#define MUTEX_CONF_HAS_MUTEX_T 1 +typedef uint8_t mutex_t; +/*---------------------------------------------------------------------------*/ +static inline bool +mutex_cortex_try_lock(volatile mutex_t *mutex) +{ + int status = 1; + + if(__LDREXB(mutex) == 0) { + status = __STREXB(1, mutex); + } -#define BUTTON_SENSOR_VALUE_TYPE_LEVEL 0 -#define BUTTON_SENSOR_VALUE_TYPE_PRESS_DURATION 1 + __DMB(); -#define BUTTON_SENSOR_PRESSED_LEVEL 0 -#define BUTTON_SENSOR_RELEASED_LEVEL 8 + return status == 0 ? true : false; +} /*---------------------------------------------------------------------------*/ -#endif /* BUTTON_SENSOR_H_ */ +static inline void +mutex_cortex_unlock(volatile mutex_t *mutex) +{ + __DMB(); + *mutex = 0; +} /*---------------------------------------------------------------------------*/ -/** - * @} - * @} - */ +#endif /* MUTEX_CORTEX_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/arch/cpu/arm/doxygen-group.txt b/arch/cpu/arm/doxygen-group.txt new file mode 100644 index 0000000000000000000000000000000000000000..8e6f294685abaab1ae01312b76fd66eb371285df --- /dev/null +++ b/arch/cpu/arm/doxygen-group.txt @@ -0,0 +1,4 @@ +/** + * \defgroup arm Support for Arm CPUs + * \ingroup cpu + */ diff --git a/arch/cpu/cc2538/Makefile.cc2538 b/arch/cpu/cc2538/Makefile.cc2538 index c7fe61496da141c32885a377112c12381cf76e1a..89121509360a046aae27b9065988f74e1cc9fe26 100644 --- a/arch/cpu/cc2538/Makefile.cc2538 +++ b/arch/cpu/cc2538/Makefile.cc2538 @@ -1,60 +1,26 @@ -CC = arm-none-eabi-gcc -CPP = arm-none-eabi-cpp -LD = arm-none-eabi-gcc -AR = arm-none-eabi-ar -OBJCOPY = arm-none-eabi-objcopy -OBJDUMP = arm-none-eabi-objdump -NM = arm-none-eabi-nm - ifndef SOURCE_LDSCRIPT SOURCE_LDSCRIPT = $(CONTIKI_CPU)/cc2538.lds endif LDSCRIPT = $(OBJECTDIR)/cc2538.ld -CFLAGS += -mcpu=cortex-m3 -mthumb -mlittle-endian -CFLAGS += -ffunction-sections -fdata-sections -CFLAGS += -fshort-enums -fomit-frame-pointer -fno-strict-aliasing -CFLAGS += -Wall -DCMSIS_DEV_HDR=\"cc2538_cm3.h\" -LDFLAGS += -mcpu=cortex-m3 -mthumb -nostartfiles -LDFLAGS += -T $(LDSCRIPT) -LDFLAGS += -Wl,--gc-sections,--sort-section=alignment -LDFLAGS += -Wl,-Map=$(@:.elf=-$(TARGET).map),--cref,--no-warn-mismatch -OBJCOPY_FLAGS += -O binary --gap-fill 0xff -OBJDUMP_FLAGS += --disassemble --source --disassembler-options=force-thumb - -ifeq ($(WERROR),1) -CFLAGS += -Werror -endif - -### Are we building with code size optimisations? -SMALL ?= 1 -ifeq ($(SMALL),1) - CFLAGS += -Os -else - CFLAGS += -O2 -endif +CFLAGS += -DCMSIS_DEV_HDR=\"cc2538_cm3.h\" ### If the user-specified a Node ID, pass a define ifdef NODEID CFLAGS += -DIEEE_ADDR_NODE_ID=$(NODEID) endif -### CPU-dependent cleanup files -CLEAN += *.d *.elf *.hex - ### CPU-dependent directories -CONTIKI_CPU_DIRS = ../arm/common/CMSIS . dev usb usb/common usb/common/cdc-acm - -### Use the existing debug I/O in arch/cpu/arm/common -CONTIKI_CPU_DIRS += ../arm/common/dbg-io +CONTIKI_CPU_DIRS = . dev usb usb/common usb/common/cdc-acm ### CPU-dependent source files CONTIKI_CPU_SOURCEFILES += soc.c clock.c rtimer-arch.c uart.c watchdog.c -CONTIKI_CPU_SOURCEFILES += nvic.c sys-ctrl.c gpio.c ioc.c spi.c adc.c +CONTIKI_CPU_SOURCEFILES += nvic.c sys-ctrl.c gpio.c ioc.c spi-legacy.c adc.c +CONTIKI_CPU_SOURCEFILES += spi-arch.c CONTIKI_CPU_SOURCEFILES += crypto.c aes.c ecb.c cbc.c ctr.c cbc-mac.c gcm.c -CONTIKI_CPU_SOURCEFILES += ccm.c sha256.c +CONTIKI_CPU_SOURCEFILES += ccm.c sha256.c gpio-hal-arch.c CONTIKI_CPU_SOURCEFILES += cc2538-aes-128.c cc2538-ccm-star.c -CONTIKI_CPU_SOURCEFILES += cc2538-rf.c udma.c lpm.c +CONTIKI_CPU_SOURCEFILES += cc2538-rf.c udma.c lpm.c int-master.c CONTIKI_CPU_SOURCEFILES += pka.c bignum-driver.c ecc-driver.c ecc-algorithm.c CONTIKI_CPU_SOURCEFILES += ecc-curve.c CONTIKI_CPU_SOURCEFILES += dbg.c ieee-addr.c @@ -62,26 +28,13 @@ CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c CONTIKI_CPU_SOURCEFILES += i2c.c cc2538-temp-sensor.c vdd3-sensor.c CONTIKI_CPU_SOURCEFILES += cfs-coffee.c cfs-coffee-arch.c pwm.c -DEBUG_IO_SOURCEFILES += dbg-printf.c dbg-snprintf.c dbg-sprintf.c strformat.c +MODULES += os/lib/dbg-io USB_SOURCEFILES += usb-core.c cdc-acm.c usb-arch.c usb-serial.c cdc-acm-descriptors.c -ifneq ($(TARGET_START_SOURCEFILES),) - CPU_START_SOURCEFILES = TARGET_START_SOURCEFILES -else - CPU_START_SOURCEFILES = startup-gcc.c -endif -CPU_STARTFILES = ${addprefix $(OBJECTDIR)/,${call oname, $(CPU_START_SOURCEFILES)}} - -CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) $(DEBUG_IO_SOURCEFILES) -CONTIKI_SOURCEFILES += $(USB_SOURCEFILES) +CPU_START_SOURCEFILES = startup-gcc.c -MODULES += lib/newlib arch/cpu/arm/common/sys - -.SECONDEXPANSION: - -### Don't treat the .elf as intermediate -.PRECIOUS: %.elf %.hex %.bin +CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) $(USB_SOURCEFILES) ### Always re-build ieee-addr.o in case the command line passes a new NODEID FORCE: @@ -90,27 +43,6 @@ $(OBJECTDIR)/ieee-addr.o: ieee-addr.c FORCE | $(OBJECTDIR) $(TRACE_CC) $(Q)$(CC) $(CFLAGS) -c $< -o $@ -### Compilation rules -CUSTOM_RULE_LINK=1 - -%.elf: $(CPU_STARTFILES) $$(CONTIKI_OBJECTFILES) %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) $(LDSCRIPT) - $(TRACE_LD) - $(Q)$(LD) $(LDFLAGS) ${filter-out $(LDSCRIPT) %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -o $@ - -%.hex: %.elf - $(OBJCOPY) -O ihex $< $@ - -%.bin: %.elf - $(OBJCOPY) $(OBJCOPY_FLAGS) $< $@ - -%.lst: %.elf - $(OBJDUMP) $(OBJDUMP_FLAGS) $< > $@ - -### We don't really need the .hex and .bin for the .$(TARGET) but let's make -### sure they get built -%.$(TARGET): %.elf %.hex %.bin - cp $< $@ - ### This rule is used to generate the correct linker script LDGENFLAGS += $(CFLAGS) LDGENFLAGS += -imacros "contiki-conf.h" -imacros "dev/cc2538-dev.h" @@ -121,3 +53,5 @@ LDGENFLAGS += -x c -P -E $(LDSCRIPT): $(SOURCE_LDSCRIPT) FORCE | $(OBJECTDIR) $(TRACE_CC) $(Q)$(CC) $(LDGENFLAGS) $< | grep -v '^\s*#\s*pragma\>' > $@ + +include $(CONTIKI)/arch/cpu/arm/cortex-m/cm3/Makefile.cm3 diff --git a/arch/cpu/cc2538/cc2538-conf.h b/arch/cpu/cc2538/cc2538-conf.h new file mode 100644 index 0000000000000000000000000000000000000000..725f95439177d86db1edbbb0c62da830667e6509 --- /dev/null +++ b/arch/cpu/cc2538/cc2538-conf.h @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc2538 + * @{ + */ +/*---------------------------------------------------------------------------*/ +#ifndef CC2538_CONF_H_ +#define CC2538_CONF_H_ +/*---------------------------------------------------------------------------*/ +/** + * \name CFS configuration + * + * @{ + */ +#ifndef COFFEE_CONF_SIZE +#define COFFEE_CONF_SIZE (4 * COFFEE_SECTOR_SIZE) +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name CC2538 System Control configuration + * + * @{ + */ +#ifndef SYS_CTRL_CONF_OSC32K_USE_XTAL +#define SYS_CTRL_CONF_OSC32K_USE_XTAL 0 /**< Use the on-board 32.768-kHz crystal */ +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Watchdog Timer configuration + * + * @{ + */ +#ifndef WATCHDOG_CONF_ENABLE +#define WATCHDOG_CONF_ENABLE 1 /**< Enable the watchdog timer */ +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name USB 'core' configuration + * + * Those values are not meant to be modified by the user, except where stated + * otherwise + * @{ + */ +#define CTRL_EP_SIZE 8 +#define USB_EP1_SIZE 32 +#define USB_EP2_SIZE 64 +#define USB_EP3_SIZE 64 +#define USB_ARCH_WRITE_NOTIFY 0 + +#ifndef USB_ARCH_CONF_DMA +#define USB_ARCH_CONF_DMA 1 /**< Change to Enable/Disable USB DMA */ + +#endif +/** @} */ +/** + * \name uDMA Configuration and channel allocations + * + * @{ + */ +#define USB_ARCH_CONF_RX_DMA_CHAN 0 /**< USB -> RAM DMA channel */ +#define USB_ARCH_CONF_TX_DMA_CHAN 1 /**< RAM -> USB DMA channel */ +#define CC2538_RF_CONF_TX_DMA_CHAN 2 /**< RF -> RAM DMA channel */ +#define CC2538_RF_CONF_RX_DMA_CHAN 3 /**< RAM -> RF DMA channel */ +#define UDMA_CONF_MAX_CHANNEL CC2538_RF_CONF_RX_DMA_CHAN +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Character I/O Configuration + * + * @{ + */ +#ifndef UART_CONF_ENABLE +#define UART_CONF_ENABLE 1 /**< Enable/Disable UART I/O */ +#endif + +#ifndef UART0_CONF_BAUD_RATE +#define UART0_CONF_BAUD_RATE 115200 /**< Default UART0 baud rate */ +#endif + +#ifndef UART1_CONF_BAUD_RATE +#define UART1_CONF_BAUD_RATE 115200 /**< Default UART1 baud rate */ +#endif + +#ifndef SLIP_ARCH_CONF_USB +#define SLIP_ARCH_CONF_USB 0 /**< SLIP over UART by default */ +#endif + +#ifndef DBG_CONF_USB +#define DBG_CONF_USB 0 /**< All debugging over UART by default */ +#endif + +#ifndef SERIAL_LINE_CONF_UART +#define SERIAL_LINE_CONF_UART 0 /**< UART to use with serial line */ +#endif + +#if !SLIP_ARCH_CONF_USB +#ifndef SLIP_ARCH_CONF_UART +#define SLIP_ARCH_CONF_UART 0 /**< UART to use with SLIP */ +#endif +#endif + +#if !DBG_CONF_USB +#ifndef DBG_CONF_UART +#define DBG_CONF_UART 0 /**< UART to use for debugging */ +#endif +#endif + +#ifndef UART1_CONF_UART +#define UART1_CONF_UART 0 /**< UART to use for examples relying on + the uart1_* API */ +#endif + +#ifndef SLIP_ARCH_CONF_ENABLED +/* + * Determine whether we need SLIP + * This will keep working while UIP_FALLBACK_INTERFACE and CMD_CONF_OUTPUT + * keep using SLIP + */ +#if defined(UIP_FALLBACK_INTERFACE) || defined(CMD_CONF_OUTPUT) +#define SLIP_ARCH_CONF_ENABLED 1 +#endif +#endif + +/** + * \brief Define this as 1 to build a headless node. + * + * The UART will not be initialised its clock will be gated, offering some + * energy savings. The USB will not be initialised either + */ +#ifndef CC2538_CONF_QUIET +#define CC2538_CONF_QUIET 0 +#endif + +/* CC2538_CONF_QUIET is hard and overrides all other related defines */ +#if CC2538_CONF_QUIET +#undef USB_SERIAL_CONF_ENABLE +#define USB_SERIAL_CONF_ENABLE 0 + +#undef UART_CONF_ENABLE +#define UART_CONF_ENABLE 0 +#endif /* CC2538_CONF_QUIET */ + +/** + * \brief Enable the USB core only if we need it + */ +#ifndef USB_SERIAL_CONF_ENABLE +#define USB_SERIAL_CONF_ENABLE \ + ((SLIP_ARCH_CONF_USB && SLIP_ARCH_CONF_ENABLED) || \ + (MAC_CONF_WITH_TSCH && (SLIP_ARCH_CONF_ENABLED || BUILD_WITH_SHELL)) || \ + DBG_CONF_USB) +#endif + +/* + * If debugging and SLIP use the same peripheral, this will be 1. Don't modify + * this + */ +#if SLIP_ARCH_CONF_ENABLED +#define DBG_CONF_SLIP_MUX (SLIP_ARCH_CONF_USB == DBG_CONF_USB && \ + (SLIP_ARCH_CONF_USB || \ + SLIP_ARCH_CONF_UART == DBG_CONF_UART)) +#endif + +/* + * Automatic detection of whether a specific UART is in use + */ +#define UART_IN_USE_BY_SERIAL_LINE(u) (SERIAL_LINE_CONF_UART == (u)) +#define UART_IN_USE_BY_SLIP(u) (SLIP_ARCH_CONF_ENABLED && \ + !SLIP_ARCH_CONF_USB && \ + SLIP_ARCH_CONF_UART == (u)) +#define UART_IN_USE_BY_DBG(u) (!DBG_CONF_USB && DBG_CONF_UART == (u)) +#define UART_IN_USE_BY_UART1(u) (UART1_CONF_UART == (u)) + +#define UART_IN_USE(u) ( \ + UART_CONF_ENABLE && \ + (UART_IN_USE_BY_SERIAL_LINE(u) || \ + UART_IN_USE_BY_SLIP(u) || \ + UART_IN_USE_BY_DBG(u) || \ + UART_IN_USE_BY_UART1(u)) \ +) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name RF configuration + * + * @{ + */ +/* RF Config */ + +#ifdef RF_CHANNEL +#define CC2538_RF_CONF_CHANNEL RF_CHANNEL +#endif + +#ifndef CC2538_RF_CONF_CHANNEL +#define CC2538_RF_CONF_CHANNEL 26 +#endif /* CC2538_RF_CONF_CHANNEL */ + +#ifndef CC2538_RF_CONF_AUTOACK +#define CC2538_RF_CONF_AUTOACK 1 /**< RF H/W generates ACKs */ +#endif /* CC2538_CONF_AUTOACK */ + +#ifndef CC2538_RF_CONF_TX_USE_DMA +#define CC2538_RF_CONF_TX_USE_DMA 1 /**< RF TX over DMA */ +#endif + +#ifndef CC2538_RF_CONF_RX_USE_DMA +#define CC2538_RF_CONF_RX_USE_DMA 1 /**< RF RX over DMA */ +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name LPM configuration + * @{ + */ +#ifndef LPM_CONF_ENABLE +#define LPM_CONF_ENABLE 1 /**< Set to 0 to disable LPM entirely */ +#endif + +/** + * \brief Maximum PM + * + * The SoC will never drop to a Power Mode deeper than the one specified here. + * 0 for PM0, 1 for PM1 and 2 for PM2 + */ +#ifndef LPM_CONF_MAX_PM +#define LPM_CONF_MAX_PM 1 +#endif + +#ifndef LPM_CONF_STATS +#define LPM_CONF_STATS 0 /**< Set to 1 to enable LPM-related stats */ +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Radio Configuration + * + * @{ + */ +#ifndef NETSTACK_CONF_RADIO +#define NETSTACK_CONF_RADIO cc2538_rf_driver +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name IEEE address configuration + * + * Used to generate our link-layer & IPv6 address + * @{ + */ +/** + * \brief Location of the IEEE address + * 0 => Read from InfoPage, + * 1 => Use a hardcoded address, configured by IEEE_ADDR_CONF_ADDRESS + */ +#ifndef IEEE_ADDR_CONF_HARDCODED +#define IEEE_ADDR_CONF_HARDCODED 0 +#endif + +/** + * \brief The hardcoded IEEE address to be used when IEEE_ADDR_CONF_HARDCODED + * is defined as 1 + */ +#ifndef IEEE_ADDR_CONF_ADDRESS +#define IEEE_ADDR_CONF_ADDRESS { 0x00, 0x12, 0x4B, 0x00, 0x89, 0xAB, 0xCD, 0xEF } +#endif + +/** + * \brief Location of the IEEE address in the InfoPage when + * IEEE_ADDR_CONF_HARDCODED is defined as 0 + * 0 => Use the primary address location + * 1 => Use the secondary address location + */ +#ifndef IEEE_ADDR_CONF_USE_SECONDARY_LOCATION +#define IEEE_ADDR_CONF_USE_SECONDARY_LOCATION 0 +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Security + * + * @{ + */ +#ifndef CRYPTO_CONF_INIT +#define CRYPTO_CONF_INIT 1 /**< Whether to init cryptoprocessor */ +#endif + +#ifndef AES_128_CONF +#define AES_128_CONF cc2538_aes_128_driver /**< AES-128 driver */ +#endif + +#ifndef CCM_STAR_CONF +#define CCM_STAR_CONF cc2538_ccm_star_driver /**< AES-CCM* driver */ +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +#endif /* CC2538_CONF_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/arch/cpu/cc2538/cc2538-def.h b/arch/cpu/cc2538/cc2538-def.h new file mode 100644 index 0000000000000000000000000000000000000000..e4c7451a6739abe7366f2dbf1dab3a1a88a76a3f --- /dev/null +++ b/arch/cpu/cc2538/cc2538-def.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#ifndef CC2538_DEF_H_ +#define CC2538_DEF_H_ +/*---------------------------------------------------------------------------*/ +#include "cm3/cm3-def.h" +/*---------------------------------------------------------------------------*/ +#define RTIMER_ARCH_SECOND 32768 +/*---------------------------------------------------------------------------*/ +/* 352us from calling transmit() until the SFD byte has been sent */ +#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(352)) +/* 192us as in datasheet but ACKs are not always received, so adjusted to 250us */ +#define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(250)) +#define RADIO_DELAY_BEFORE_DETECT 0 +#ifndef TSCH_CONF_BASE_DRIFT_PPM +/* The drift compared to "true" 10ms slots. + * Enable adaptive sync to enable compensation for this. + * Slot length 10000 usec + * 328 ticks + * Tick duration 30.517578125 usec + * Real slot duration 10009.765625 usec + * Target - real duration = -9.765625 usec + * TSCH_CONF_BASE_DRIFT_PPM -977 + */ +#define TSCH_CONF_BASE_DRIFT_PPM -977 +#endif + +#if MAC_CONF_WITH_TSCH +#define TSCH_CONF_HW_FRAME_FILTERING 0 +#endif /* MAC_CONF_WITH_TSCH */ +/*---------------------------------------------------------------------------*/ +#define SPI_CONF_CONTROLLER_COUNT 2 +/*---------------------------------------------------------------------------*/ +/* Path to CMSIS header */ +#define CMSIS_CONF_HEADER_PATH "cc2538_cm3.h" + +/* Path to headers with implementation of mutexes and memory barriers */ +#define MUTEX_CONF_ARCH_HEADER_PATH "mutex-cortex.h" +#define MEMORY_BARRIER_CONF_ARCH_HEADER_PATH "memory-barrier-cortex.h" + +#define GPIO_HAL_CONF_ARCH_HDR_PATH "dev/gpio-hal-arch.h" +/*---------------------------------------------------------------------------*/ +#endif /* CC2538_DEF_H_ */ +/*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/cc2538/cc2538.lds b/arch/cpu/cc2538/cc2538.lds index ef465409e3d03e5f5a441af3e725f76ed1604f36..4d5031f15d0000d5ab2232482354930096ca2ba5 100644 --- a/arch/cpu/cc2538/cc2538.lds +++ b/arch/cpu/cc2538/cc2538.lds @@ -96,11 +96,18 @@ SECTIONS _ebss = .; } > FRSRAM + _end = .; /* End of the .bss segment. */ + + /* This symbol is used by the stack check library. */ + _stack = .; + .stack (NOLOAD) : { *(.stack) } > FRSRAM + /* This symbol is used by the stack check library. */ + _stack_origin = .; _heap = .; _eheap = ORIGIN(FRSRAM) + LENGTH(FRSRAM); diff --git a/arch/cpu/cc2538/clock.c b/arch/cpu/cc2538/clock.c index 2842a3be8abc463859008523e14631af617af942..839c722428932abfa8bd8124a2d1e030c045d22f 100644 --- a/arch/cpu/cc2538/clock.c +++ b/arch/cpu/cc2538/clock.c @@ -114,7 +114,7 @@ clock_init(void) REG(GPT_0_BASE + GPTIMER_TAPR) = PRESCALER_VALUE; } /*---------------------------------------------------------------------------*/ -CCIF clock_time_t +clock_time_t clock_time(void) { return rt_ticks_startup / RTIMER_CLOCK_TICK_RATIO; @@ -126,7 +126,7 @@ clock_set_seconds(unsigned long sec) rt_ticks_epoch = (uint64_t)sec * RTIMER_SECOND; } /*---------------------------------------------------------------------------*/ -CCIF unsigned long +unsigned long clock_seconds(void) { return rt_ticks_epoch / RTIMER_SECOND; diff --git a/arch/cpu/cc2538/cpu.h b/arch/cpu/cc2538/cpu.h index eb86e6655c819a33bdd8fbc45ea481be86209745..4ed9aa56f05831f6237eb485cd1e7e005fd7c6d7 100644 --- a/arch/cpu/cc2538/cpu.h +++ b/arch/cpu/cc2538/cpu.h @@ -29,16 +29,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /** - * \addtogroup platform - * @{ - * - * \defgroup cc2538-platforms TI cc2538-powered platforms - * - * Documentation for all platforms powered by the TI cc2538 System-on-Chip - * @{ - * - * \defgroup cc2538 The TI cc2538 System-on-Chip - * CPU-Specific functionality - available to all cc2538-based platforms + * \addtogroup cc2538 * @{ * * \defgroup cc2538-cpu cc2538 CPU @@ -65,8 +56,6 @@ #endif /* CPU_H_ */ /** - * @} - * @} * @} * @} */ diff --git a/arch/cpu/cc2538/dbg.c b/arch/cpu/cc2538/dbg.c index b97936febf631eea2b4b440840e2a1ba97c15ba6..7b33bc4716c4ce8738ce4ad39e6c5b8059dbdaf0 100644 --- a/arch/cpu/cc2538/dbg.c +++ b/arch/cpu/cc2538/dbg.c @@ -28,16 +28,9 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** \addtogroup cc2538-char-io - * @{ */ -/** - * \file - * Implementation of arch-specific functions required by the dbg_io API in - * cpu/arm/common/dbg-io - */ +/*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "dbg.h" #include "dev/uart.h" #include "usb/usb-serial.h" @@ -55,13 +48,10 @@ #define flush() #endif /*---------------------------------------------------------------------------*/ -#undef putchar -#undef puts - #define SLIP_END 0300 /*---------------------------------------------------------------------------*/ int -putchar(int c) +dbg_putchar(int c) { #if DBG_CONF_SLIP_MUX static char debug_frame = 0; @@ -80,7 +70,7 @@ putchar(int c) write_byte(SLIP_END); debug_frame = 0; #endif - dbg_flush(); + flush(); } return c; } @@ -100,18 +90,3 @@ dbg_send_bytes(const unsigned char *s, unsigned int len) return i; } /*---------------------------------------------------------------------------*/ -int -puts(const char *s) -{ - unsigned int i = 0; - - while(s && *s != 0) { - putchar(*s++); - i++; - } - putchar('\n'); - return i; -} -/*---------------------------------------------------------------------------*/ - -/** @} */ diff --git a/arch/cpu/cc2538/dbg.h b/arch/cpu/cc2538/dbg.h deleted file mode 100644 index d5ab51f9d4c0dc5fdeeb54992f0c5ce0652d4da1..0000000000000000000000000000000000000000 --- a/arch/cpu/cc2538/dbg.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \addtogroup cc2538 - * @{ - * - * \defgroup cc2538-char-io cc2538 Character I/O - * - * CPU-specific functions for debugging and SLIP I/O - * - * On the cc2538, character I/O can be directed over USB or UART. This is - * controlled by a series of configuration directives: - * - SLIP_ARCH_CONF_USB: Controls the operation of slip-arch. - * - DBG_CONF_USB: Controls all debugging output - * - * Defaults for those defines are set in contiki-conf.h - * @{ - * - * \file - * Header file for the cc2538 Debug I/O module - */ -#ifndef DBG_H_ -#define DBG_H_ - -#include "contiki.h" - -#include "usb/usb-serial.h" -/** - * \brief Print a stream of bytes - * \param seq A pointer to the stream - * \param len The number of bytes to print - * \return The number of printed bytes - * - * This function is an arch-specific implementation required by the dbg-io - * API in cpu/arm/common/dbg-io. It prints a stream of bytes over the - * peripheral used by the platform. - */ -unsigned int dbg_send_bytes(const unsigned char *seq, unsigned int len); - -/** - * \brief Flushes character output - * - * When debugging is sent over USB, this functions causes the USB - * driver to immediately TX the content of output buffers. When - * debugging is over UART, this function does nothing. - * - * There is nothing stopping you from using this macro in your code but - * normally, you won't have to. - */ -#if DBG_CONF_USB -#define dbg_flush() usb_serial_flush() -#else -#define dbg_flush() -#endif - -#endif /* DBG_H_ */ - -/** - * @} - * @} - */ diff --git a/arch/cpu/cc2538/dev/gpio-hal-arch.c b/arch/cpu/cc2538/dev/gpio-hal-arch.c new file mode 100644 index 0000000000000000000000000000000000000000..bd2dfb92d8d57e58c2f9f84fd85a0b2c7beed6b5 --- /dev/null +++ b/arch/cpu/cc2538/dev/gpio-hal-arch.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc2538-gpio-hal + * @{ + * + * \file + * Implementation file for the CC2538 GPIO HAL functions + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +#include "dev/gpio.h" +#include "dev/ioc.h" + +#include <stdint.h> +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg) +{ + uint8_t port, pin_num, pin_mask; + uint32_t port_base; + + port = PIN_TO_PORT(pin); + port_base = PIN_TO_PORT_BASE(pin); + pin_num = pin % 8; + pin_mask = GPIO_PIN_MASK(pin_num); + + gpio_hal_pin_cfg_t tmp; + + tmp = cfg & GPIO_HAL_PIN_CFG_EDGE_BOTH; + if(tmp == GPIO_HAL_PIN_CFG_EDGE_NONE) { + GPIO_DISABLE_INTERRUPT(port_base, pin_mask); + } else if(tmp == GPIO_HAL_PIN_CFG_EDGE_RISING) { + GPIO_DETECT_EDGE(port_base, pin_mask); + GPIO_TRIGGER_SINGLE_EDGE(port_base, pin_mask); + GPIO_DETECT_RISING(port_base, pin_mask); + } else if(tmp == GPIO_HAL_PIN_CFG_EDGE_FALLING) { + GPIO_DETECT_EDGE(port_base, pin_mask); + GPIO_TRIGGER_SINGLE_EDGE(port_base, pin_mask); + GPIO_DETECT_FALLING(port_base, pin_mask); + } else if(tmp == GPIO_HAL_PIN_CFG_EDGE_BOTH) { + GPIO_DETECT_EDGE(port_base, pin_mask); + GPIO_TRIGGER_BOTH_EDGES(port_base, pin_mask); + } + + tmp = cfg & GPIO_HAL_PIN_CFG_PULL_MASK; + if(tmp == GPIO_HAL_PIN_CFG_PULL_NONE) { + ioc_set_over(port, pin_num, IOC_OVERRIDE_DIS); + } else if(tmp == GPIO_HAL_PIN_CFG_PULL_DOWN) { + ioc_set_over(port, pin_num, IOC_OVERRIDE_PDE); + } else if(tmp == GPIO_HAL_PIN_CFG_PULL_UP) { + ioc_set_over(port, pin_num, IOC_OVERRIDE_PUE); + } + + tmp = cfg & GPIO_HAL_PIN_CFG_INT_MASK; + if(tmp == GPIO_HAL_PIN_CFG_INT_DISABLE) { + GPIO_DISABLE_INTERRUPT(port_base, pin_mask); + } else if(tmp == GPIO_HAL_PIN_CFG_INT_ENABLE) { + GPIO_ENABLE_INTERRUPT(port_base, pin_mask); + NVIC_EnableIRQ(port); + } + + GPIO_SOFTWARE_CONTROL(port_base, pin_mask); +} +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_cfg_t +gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin) +{ + uint8_t port, pin_num, pin_mask; + uint32_t port_base; + gpio_hal_pin_cfg_t cfg; + uint32_t tmp; + + port = PIN_TO_PORT(pin); + port_base = PIN_TO_PORT_BASE(pin); + pin_num = pin % 8; + pin_mask = GPIO_PIN_MASK(pin_num); + + cfg = 0; + + /* Pull */ + tmp = ioc_get_over(port, pin_num); + if(tmp == IOC_OVERRIDE_PUE) { + cfg |= GPIO_HAL_PIN_CFG_PULL_UP; + } else if(tmp == IOC_OVERRIDE_PDE) { + cfg |= GPIO_HAL_PIN_CFG_PULL_DOWN; + } else { + cfg |= GPIO_HAL_PIN_CFG_PULL_NONE; + } + + /* Interrupt enable/disable */ + tmp = REG((port_base) + GPIO_IE) & pin_mask; + if(tmp == 0) { + cfg |= GPIO_HAL_PIN_CFG_INT_DISABLE; + } else { + cfg |= GPIO_HAL_PIN_CFG_INT_ENABLE; + } + + /* Edge detection */ + if(REG((port_base) + GPIO_IS) & pin_mask) { + cfg |= GPIO_HAL_PIN_CFG_EDGE_NONE; + } else { + if(REG((port_base) + GPIO_IBE) & pin_mask) { + cfg |= GPIO_HAL_PIN_CFG_EDGE_BOTH; + } else { + if(REG((port_base) + GPIO_IEV) & pin_mask) { + cfg |= GPIO_HAL_PIN_CFG_EDGE_RISING; + } else { + cfg |= GPIO_HAL_PIN_CFG_EDGE_FALLING; + } + } + } + + return cfg; +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_write_pin(gpio_hal_pin_t pin, uint8_t value) +{ + if(value == 1) { + gpio_hal_arch_set_pin(pin); + return; + } + gpio_hal_arch_clear_pin(pin); +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_set_pins(gpio_hal_pin_mask_t pins) +{ + GPIO_SET_PIN(GPIO_A_BASE, pins & 0xFF); + GPIO_SET_PIN(GPIO_B_BASE, (pins >> 8) & 0xFF); + GPIO_SET_PIN(GPIO_C_BASE, (pins >> 16) & 0xFF); + GPIO_SET_PIN(GPIO_D_BASE, (pins >> 24) & 0xFF); +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_clear_pins(gpio_hal_pin_mask_t pins) +{ + GPIO_CLR_PIN(GPIO_A_BASE, pins & 0xFF); + GPIO_CLR_PIN(GPIO_B_BASE, (pins >> 8) & 0xFF); + GPIO_CLR_PIN(GPIO_C_BASE, (pins >> 16) & 0xFF); + GPIO_CLR_PIN(GPIO_D_BASE, (pins >> 24) & 0xFF); +} +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_mask_t +gpio_hal_arch_read_pins(gpio_hal_pin_mask_t pins) +{ + gpio_hal_pin_mask_t rv = 0; + + rv |= GPIO_READ_PIN(GPIO_A_BASE, pins & 0xFF); + rv |= GPIO_READ_PIN(GPIO_B_BASE, (pins >> 8) & 0xFF) << 8; + rv |= GPIO_READ_PIN(GPIO_C_BASE, (pins >> 16) & 0xFF) << 16; + rv |= GPIO_READ_PIN(GPIO_D_BASE, (pins >> 24) & 0xFF) << 24; + + return rv; +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_write_pins(gpio_hal_pin_mask_t pins, gpio_hal_pin_mask_t value) +{ + GPIO_WRITE_PIN(GPIO_A_BASE, pins & 0xFF, value & 0xFF); + GPIO_WRITE_PIN(GPIO_B_BASE, (pins >> 8) & 0xFF, (value >> 8) & 0xFF); + GPIO_WRITE_PIN(GPIO_C_BASE, (pins >> 16) & 0xFF, (value >> 16) & 0xFF); + GPIO_WRITE_PIN(GPIO_D_BASE, (pins >> 24) & 0xFF, (value >> 24) & 0xFF); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/arch/cpu/cc2538/dev/gpio-hal-arch.h b/arch/cpu/cc2538/dev/gpio-hal-arch.h new file mode 100644 index 0000000000000000000000000000000000000000..25abb3eb4fec0bc0fa78c4cd24111fcaffdef9f1 --- /dev/null +++ b/arch/cpu/cc2538/dev/gpio-hal-arch.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc2538 + * @{ + * + * \defgroup cc2538-gpio-hal CC2538 GPIO HAL implementation + * + * @{ + * + * \file + * Header file for the CC2538 GPIO HAL functions + * + * \note + * Do not include this header directly + */ +/*---------------------------------------------------------------------------*/ +#ifndef GPIO_HAL_ARCH_H_ +#define GPIO_HAL_ARCH_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio.h" + +#include <stdint.h> +/*---------------------------------------------------------------------------*/ +#define PIN_TO_PORT(pin) (pin >> 3) +#define PIN_TO_NUM(pin) (pin % 8) +#define PIN_TO_PORT_BASE(pin) GPIO_PORT_TO_BASE(PIN_TO_PORT(pin)) +/*---------------------------------------------------------------------------*/ +#define gpio_hal_arch_interrupt_enable(p) do { \ + GPIO_ENABLE_INTERRUPT(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \ + NVIC_EnableIRQ(PIN_TO_PORT(p)); \ +} while(0); + +#define gpio_hal_arch_interrupt_disable(p) \ + GPIO_DISABLE_INTERRUPT(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)) + +#define gpio_hal_arch_pin_set_input(p) do { \ + GPIO_SOFTWARE_CONTROL(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \ + GPIO_SET_INPUT(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \ +} while(0); + +#define gpio_hal_arch_pin_set_output(p) do { \ + GPIO_SOFTWARE_CONTROL(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \ + GPIO_SET_OUTPUT(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \ +} while(0); + +#define gpio_hal_arch_set_pin(p) \ + GPIO_SET_PIN(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)) + +#define gpio_hal_arch_clear_pin(p) \ + GPIO_CLR_PIN(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)) + +#define gpio_hal_arch_read_pin(p) \ + (GPIO_READ_PIN(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)) == 0 ? 0 : 1) +/*---------------------------------------------------------------------------*/ +#endif /* GPIO_HAL_ARCH_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/arch/cpu/cc2538/dev/gpio.c b/arch/cpu/cc2538/dev/gpio.c index a09ca6dc38e58aef880a057b8fe6fa3b101d993c..c5c72594bd6e60ebb133c51c7cf35439c1755f44 100644 --- a/arch/cpu/cc2538/dev/gpio.c +++ b/arch/cpu/cc2538/dev/gpio.c @@ -37,46 +37,13 @@ */ #include "contiki.h" #include "dev/leds.h" +#include "dev/gpio-hal.h" #include "dev/gpio.h" #include "dev/nvic.h" #include "reg.h" #include "lpm.h" #include <string.h> - -/** - * \brief Pointer to a function to be called when a GPIO interrupt is detected. - * Callbacks for Port A, Pins[0:7] are stored in positions [0:7] of this - * buffer, Port B callbacks in [8:15] and so on - */ -static gpio_callback_t gpio_callbacks[32]; -/*---------------------------------------------------------------------------*/ -void -gpio_register_callback(gpio_callback_t f, uint8_t port, uint8_t pin) -{ - gpio_callbacks[(port << 3) + pin] = f; -} -/*---------------------------------------------------------------------------*/ -/** \brief Run through all registered GPIO callbacks and invoke those - * associated with the \a port and the pins specified by \a mask - * \param mask Search callbacks associated with pins specified by this mask - * \param port Search callbacks associated with this port. Here, port is - * specified as a number between 0 and 3. Port A: 0, Port B: 1 etc */ -void -notify(uint8_t mask, uint8_t port) -{ - uint8_t i; - gpio_callback_t *f = &gpio_callbacks[port << 3]; - - for(i = 0; i < 8; i++) { - if(mask & (1 << i)) { - if((*f) != NULL) { - (*f)(port, i); - } - } - f++; - } -} /*---------------------------------------------------------------------------*/ /** \brief Interrupt service routine for Port \a port * \param port Number between 0 and 3. Port A: 0, Port B: 1, etc. @@ -93,7 +60,7 @@ gpio_port_isr(uint8_t port) int_status = GPIO_GET_MASKED_INT_STATUS(base); power_up_int_status = GPIO_GET_POWER_UP_INT_STATUS(port); - notify(int_status | power_up_int_status, port); + gpio_hal_event_handler((int_status | power_up_int_status) << (port << 3)); GPIO_CLEAR_INTERRUPT(base, int_status); GPIO_CLEAR_POWER_UP_INTERRUPT(port, power_up_int_status); @@ -110,9 +77,4 @@ GPIO_PORT_ISR(b, B) GPIO_PORT_ISR(c, C) GPIO_PORT_ISR(d, D) /*---------------------------------------------------------------------------*/ -void -gpio_init() -{ - memset(gpio_callbacks, 0, sizeof(gpio_callbacks)); -} /** @} */ diff --git a/arch/cpu/cc2538/dev/gpio.h b/arch/cpu/cc2538/dev/gpio.h index 00ee1b1dc7bbe727bb1b915a001edc9ce37525c9..67b28cf0d55368a66365ecdb29e49b21d1fbe9d4 100644 --- a/arch/cpu/cc2538/dev/gpio.h +++ b/arch/cpu/cc2538/dev/gpio.h @@ -42,27 +42,12 @@ */ #ifndef GPIO_H_ #define GPIO_H_ - +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" #include "reg.h" #include <stdint.h> - -/** - * \brief Type definition for callbacks invoked by the GPIO ISRs - * \param port The port that triggered the GPIO interrupt. \e port is passed - * by its numeric representation (Port A:0, B:1 etc). Defines for - * these numeric representations are GPIO_x_NUM - * \param pin The pin that triggered the interrupt, specified by number - * (0, 1, ..., 7) - * - * This is the prototype of a function pointer passed to - * gpio_register_callback(). These callbacks are registered on a port/pin - * basis. When a GPIO port generates an interrupt, if a callback has been - * registered for the port/pin combination, the ISR will invoke it. The ISR - * will pass the port/pin as arguments in that call, so that a developer can - * re-use the same callback for multiple port/pin combinations - */ -typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); /*---------------------------------------------------------------------------*/ /** \name Base addresses for the GPIO register instances * @{ @@ -341,6 +326,14 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * number. */ #define GPIO_PORT_TO_BASE(PORT) (GPIO_A_BASE + ((PORT) << 12)) + +/** + * \brief Converts a port/pin pair to GPIO HAL pin number + * \param PORT The port number in the range 0 - 3 (GPIO_n_NUM). + * \param PIN The pin number in the range 0 - 7. + * \return The pin representation using GPIO HAL semantics + */ +#define GPIO_PORT_PIN_TO_GPIO_HAL_PIN(PORT, PIN) (((PORT) << 3) + (PIN)) /** @} */ /*---------------------------------------------------------------------------*/ /** \name GPIO Register offset declarations @@ -612,21 +605,6 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); #define GPIO_IRQ_DETECT_UNMASK_PAIACK0 0x00000001 /**< Port A bit 0 */ /** @} */ /*---------------------------------------------------------------------------*/ -/** \brief Initialise the GPIO module */ -void gpio_init(); - -/** - * \brief Register GPIO callback - * \param f Pointer to a function to be called when \a pin of \a port - * generates an interrupt - * \param port Associate \a f with this port. \e port must be specified with - * its numeric representation (Port A:0, B:1 etc). Defines for these - * numeric representations are GPIO_x_NUM - * \param pin Associate \a f with this pin, which is specified by number - * (0, 1, ..., 7) - */ -void gpio_register_callback(gpio_callback_t f, uint8_t port, uint8_t pin); - #endif /* GPIO_H_ */ /** diff --git a/arch/cpu/cc2538/dev/ioc.c b/arch/cpu/cc2538/dev/ioc.c index 53a9218a9907bee37c54e7d493781e2fcf00c6d2..5bb631c4681aba5f80b4ffad2591bf90278fc1bc 100644 --- a/arch/cpu/cc2538/dev/ioc.c +++ b/arch/cpu/cc2538/dev/ioc.c @@ -56,6 +56,12 @@ ioc_set_over(uint8_t port, uint8_t pin, uint8_t over) ioc_over[(port << 3) + pin] = over; } /*---------------------------------------------------------------------------*/ +uint32_t +ioc_get_over(uint8_t port, uint8_t pin) +{ + return ioc_over[(port << 3) + pin] & 0x0F; +} +/*---------------------------------------------------------------------------*/ void ioc_set_sel(uint8_t port, uint8_t pin, uint8_t sel) { diff --git a/arch/cpu/cc2538/dev/ioc.h b/arch/cpu/cc2538/dev/ioc.h index 7fad9d2755a3eeec086bec9c9d3ef2c3adf2e5dc..ae14a616f8c2400e9100196f1e86896c8c479f6d 100644 --- a/arch/cpu/cc2538/dev/ioc.h +++ b/arch/cpu/cc2538/dev/ioc.h @@ -249,6 +249,22 @@ void ioc_init(); */ void ioc_set_over(uint8_t port, uint8_t pin, uint8_t over); +/** + * \brief Get Port:Pin override function + * \param port The port as a number (PA: 0, PB: 1 etc) + * \param pin The pin as a number + * \return The override function + * + * The return value can be one of + * + * - IOC_OVERRIDE_OE: Output + * - IOC_OVERRIDE_PUE: Pull-Up + * - IOC_OVERRIDE_PDE: Pull-Down + * - IOC_OVERRIDE_ANA: Analog + * - IOC_OVERRIDE_DIS: Disabled + */ +uint32_t ioc_get_over(uint8_t port, uint8_t pin); + /** * \brief Function select for Port:Pin * \param port The port as a number (PA: 0, PB: 1 etc) diff --git a/arch/cpu/cc2538/spi-arch.h b/arch/cpu/cc2538/dev/spi-arch-legacy.h similarity index 93% rename from arch/cpu/cc2538/spi-arch.h rename to arch/cpu/cc2538/dev/spi-arch-legacy.h index 8cbb87a8f580137132b2820d4c4008ae6b356d0a..9608110ed91bceed9957be8e501c7ae5db855e73 100644 --- a/arch/cpu/cc2538/spi-arch.h +++ b/arch/cpu/cc2538/dev/spi-arch-legacy.h @@ -55,7 +55,7 @@ * - SPIX_FLUSH(x) * * Some of the old functions and macros are still supported. - * When using these deprecated functions, the SSI module to use + * When using these deprecated functions, the SSI module to use * has to be be selected by means of the macro SPI_CONF_DEFAULT_INSTANCE. * * This SPI driver depends on the following defines: @@ -78,8 +78,8 @@ * - SPI1_RX_PORT * - SPI1_RX_PIN */ -#ifndef SPI_ARCH_H_ -#define SPI_ARCH_H_ +#ifndef SPI_ARCH_LEGACY_H_ +#define SPI_ARCH_LEGACY_H_ #include "contiki.h" @@ -95,14 +95,14 @@ #endif /*---------------------------------------------------------------------------*/ /* Default values for the clock rate divider */ -#ifdef SPI0_CONF_CPRS_CPSDVSR -#define SPI0_CPRS_CPSDVSR SPI0_CONF_CPRS_CPSDVSR +#ifdef SPI0_CONF_CPRS_CPSDVSR +#define SPI0_CPRS_CPSDVSR SPI0_CONF_CPRS_CPSDVSR #else #define SPI0_CPRS_CPSDVSR 2 #endif -#ifdef SPI1_CONF_CPRS_CPSDVSR -#define SPI1_CPRS_CPSDVSR SPI1_CONF_CPRS_CPSDVSR +#ifdef SPI1_CONF_CPRS_CPSDVSR +#define SPI1_CPRS_CPSDVSR SPI1_CONF_CPRS_CPSDVSR #else #define SPI1_CPRS_CPSDVSR 2 #endif @@ -120,7 +120,7 @@ } while(0) #define SPIX_FLUSH(spi) do { \ while(REG(SSI_BASE(spi) + SSI_SR) & SSI_SR_RNE) { \ - SPIX_BUF(spi); \ + SPIX_BUF(spi); \ } \ } while(0) #define SPIX_CS_CLR(port, pin) do { \ @@ -138,13 +138,13 @@ #define SPI_WAITFOREOTx() SPIX_WAITFOREOTx(SPI_DEFAULT_INSTANCE) #define SPI_WAITFOREORx() SPIX_WAITFOREORx(SPI_DEFAULT_INSTANCE) #ifdef SPI_FLUSH -#error You must include spi-arch.h before spi.h for the CC2538 +#error You must include spi-arch-legacy.h before spi-legacy.h for the CC2538 #else #define SPI_FLUSH() SPIX_FLUSH(SPI_DEFAULT_INSTANCE) #endif #define SPI_CS_CLR(port, pin) SPIX_CS_CLR(port, pin) #define SPI_CS_SET(port, pin) SPIX_CS_SET(port, pin) -#endif /* #ifdef SPI_DEFAULT_INSTANCE */ +#endif /* #ifdef SPI_DEFAULT_INSTANCE */ /*---------------------------------------------------------------------------*/ /** \name Arch-specific SPI functions * @{ @@ -183,7 +183,7 @@ void spix_disable(uint8_t spi); * * See section 19.4.4 in the CC2538 user guide for more information. * - * \param spi The SSI instance to use. + * \param spi The SSI instance to use. * \param frame_format Set the SSI frame format. Use SSI_CR0_FRF_MOTOROLA, * SSI_CR0_FRF_TI, or SSI_CR0_FRF_MICROWIRE. * \param clock_polarity In Motorola mode, set whether the clock is high or low @@ -215,7 +215,7 @@ void spix_cs_init(uint8_t port, uint8_t pin); /** @} */ -#endif /* SPI_ARCH_H_ */ +#endif /* SPI_ARCH_LEGACY_H_ */ /** * @} diff --git a/arch/cpu/cc2538/dev/spi-arch.c b/arch/cpu/cc2538/dev/spi-arch.c new file mode 100644 index 0000000000000000000000000000000000000000..c876e4ed749a3c11346f33856c17f327c18968ca --- /dev/null +++ b/arch/cpu/cc2538/dev/spi-arch.c @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2016-2017, Yanzi Networks. + * Copyright (c) 2018, University of Bristol. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdint.h> +#include "contiki.h" +#include "reg.h" +#include "dev/spi.h" +#include "gpio-hal-arch.h" +#include "sys/cc.h" +#include "ioc.h" +#include "sys-ctrl.h" +#include "ssi.h" +#include "gpio.h" +#include "sys/log.h" +#include "sys/mutex.h" +/*---------------------------------------------------------------------------*/ +/* Log configuration */ +#define LOG_MODULE "spi-hal-arch" +#define LOG_LEVEL LOG_LEVEL_NONE +/*---------------------------------------------------------------------------*/ +/* Default values for the clock rate divider */ +#ifdef SPI_ARCH_CONF_SPI0_CPRS_CPSDVSR +#define SPI_ARCH_SPI0_CPRS_CPSDVSR SPI_ARCH_CONF_SPI0_CPRS_CPSDVSR +#else +#define SPI_ARCH_SPI0_CPRS_CPSDVSR 2 +#endif + +#ifdef SPI_ARCH_CONF_SPI1_CPRS_CPSDVSR +#define SPI_ARCH_SPI1_CPRS_CPSDVSR SPI_ARCH_CONF_SPI1_CPRS_CPSDVSR +#else +#define SPI_ARCH_SPI1_CPRS_CPSDVSR 2 +#endif + +#if (SPI_ARCH_SPI0_CPRS_CPSDVSR & 1) == 1 || \ + SPI_ARCH_SPI0_CPRS_CPSDVSR < 2 || \ + SPI_ARCH_SPI0_CPRS_CPSDVSR > 254 +#error SPI_ARCH_SPI0_CPRS_CPSDVSR must be an even number between 2 and 254 +#endif + +#if (SPI_ARCH_SPI1_CPRS_CPSDVSR & 1) == 1 || \ + SPI_ARCH_SPI1_CPRS_CPSDVSR < 2 || \ + SPI_ARCH_SPI1_CPRS_CPSDVSR > 254 +#error SPI_ARCH_SPI1_CPRS_CPSDVSR must be an even number between 2 and 254 +#endif +/*---------------------------------------------------------------------------*/ +/* CS set and clear macros */ +#define SPIX_CS_CLR(port, pin) GPIO_CLR_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)) +#define SPIX_CS_SET(port, pin) GPIO_SET_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)) +/*---------------------------------------------------------------------------*/ +/* + * Clock source from which the baud clock is determined for the SSI, according + * to SSI_CC.CS. + */ +#define SSI_SYS_CLOCK SYS_CTRL_SYS_CLOCK +/*---------------------------------------------------------------------------*/ +typedef struct { + uint32_t base; + uint32_t ioc_ssirxd_ssi; + uint32_t ioc_pxx_sel_ssi_clkout; + uint32_t ioc_pxx_sel_ssi_txd; + uint8_t ssi_cprs_cpsdvsr; +} spi_regs_t; +/*---------------------------------------------------------------------------*/ +static const spi_regs_t spi_regs[SSI_INSTANCE_COUNT] = { + { + .base = SSI0_BASE, + .ioc_ssirxd_ssi = IOC_SSIRXD_SSI0, + .ioc_pxx_sel_ssi_clkout = IOC_PXX_SEL_SSI0_CLKOUT, + .ioc_pxx_sel_ssi_txd = IOC_PXX_SEL_SSI0_TXD, + .ssi_cprs_cpsdvsr = SPI_ARCH_SPI0_CPRS_CPSDVSR, + }, { + .base = SSI1_BASE, + .ioc_ssirxd_ssi = IOC_SSIRXD_SSI1, + .ioc_pxx_sel_ssi_clkout = IOC_PXX_SEL_SSI1_CLKOUT, + .ioc_pxx_sel_ssi_txd = IOC_PXX_SEL_SSI1_TXD, + .ssi_cprs_cpsdvsr = SPI_ARCH_SPI1_CPRS_CPSDVSR, + } +}; + +typedef struct spi_locks_s { + mutex_t lock; + spi_device_t *owner; +} spi_locks_t; + +/* One lock per SPI controller */ +spi_locks_t board_spi_locks_spi[SPI_CONTROLLER_COUNT] = { { MUTEX_STATUS_UNLOCKED, NULL } }; + +/*---------------------------------------------------------------------------*/ +static void +spix_wait_tx_ready(spi_device_t *dev) +{ + /* Infinite loop until SR_TNF - Transmit FIFO Not Full */ + while(!(REG(spi_regs[dev->spi_controller].base + SSI_SR) & SSI_SR_TNF)); +} +/*---------------------------------------------------------------------------*/ +static int +spix_read_buf(spi_device_t *dev) +{ + return REG(spi_regs[dev->spi_controller].base + SSI_DR); +} +/*---------------------------------------------------------------------------*/ +static void +spix_write_buf(spi_device_t *dev, int data) +{ + REG(spi_regs[dev->spi_controller].base + SSI_DR) = data; +} +/*---------------------------------------------------------------------------*/ +static void +spix_wait_eotx(spi_device_t *dev) +{ + /* wait until not busy */ + while(REG(spi_regs[dev->spi_controller].base + SSI_SR) & SSI_SR_BSY); +} +/*---------------------------------------------------------------------------*/ +static void +spix_wait_eorx(spi_device_t *dev) +{ + /* wait as long as receive is empty */ + while(!(REG(spi_regs[dev->spi_controller].base + SSI_SR) & SSI_SR_RNE)); +} +/*---------------------------------------------------------------------------*/ +bool +spi_arch_has_lock(spi_device_t *dev) +{ + if(board_spi_locks_spi[dev->spi_controller].owner == dev) { + return true; + } + + return false; +} +/*---------------------------------------------------------------------------*/ +bool +spi_arch_is_bus_locked(spi_device_t *dev) +{ + if(board_spi_locks_spi[dev->spi_controller].lock == MUTEX_STATUS_LOCKED) { + return true; + } + + return false; +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_arch_lock_and_open(spi_device_t *dev) +{ + const spi_regs_t *regs; + uint32_t scr; + uint64_t div; + + uint32_t cs_port = PIN_TO_PORT(dev->pin_spi_cs); + uint32_t cs_pin = PIN_TO_NUM(dev->pin_spi_cs); + + uint32_t clk_port = PIN_TO_PORT(dev->pin_spi_sck); + uint32_t clk_pin = PIN_TO_NUM(dev->pin_spi_sck); + + uint32_t miso_port = PIN_TO_PORT(dev->pin_spi_miso); + uint32_t miso_pin = PIN_TO_NUM(dev->pin_spi_miso); + + uint32_t mosi_port = PIN_TO_PORT(dev->pin_spi_mosi); + uint32_t mosi_pin = PIN_TO_NUM(dev->pin_spi_mosi); + + uint32_t mode = 0; + + /* lock the SPI bus */ + if(mutex_try_lock(&board_spi_locks_spi[dev->spi_controller].lock) == false) { + return SPI_DEV_STATUS_BUS_LOCKED; + } + + board_spi_locks_spi[dev->spi_controller].owner = dev; + + /* Set SPI phase */ + if(dev->spi_pha != 0) { + mode = mode | SSI_CR0_SPH; + } + + /* Set SPI polarity */ + if(dev->spi_pol != 0) { + mode = mode | SSI_CR0_SPO; + } + + /* CS pin configuration */ + GPIO_SOFTWARE_CONTROL(GPIO_PORT_TO_BASE(cs_port), + GPIO_PIN_MASK(cs_pin)); + ioc_set_over(cs_port, cs_pin, IOC_OVERRIDE_DIS); + GPIO_SET_OUTPUT(GPIO_PORT_TO_BASE(cs_port), GPIO_PIN_MASK(cs_pin)); + GPIO_SET_PIN(GPIO_PORT_TO_BASE(cs_port), GPIO_PIN_MASK(cs_pin)); + + regs = &spi_regs[dev->spi_controller]; + + /* SSI Enable */ + REG(SYS_CTRL_RCGCSSI) |= (1 << dev->spi_controller); + + /* Start by disabling the peripheral before configuring it */ + REG(regs->base + SSI_CR1) = 0; + + /* Set the system clock as the SSI clock */ + REG(regs->base + SSI_CC) = 0; + + /* Set the mux correctly to connect the SSI pins to the correct GPIO pins */ + ioc_set_sel(clk_port, clk_pin, regs->ioc_pxx_sel_ssi_clkout); + ioc_set_sel(mosi_port, mosi_pin, regs->ioc_pxx_sel_ssi_txd); + REG(regs->ioc_ssirxd_ssi) = dev->pin_spi_miso; + + /* Put all the SSI gpios into peripheral mode */ + GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(clk_port), + GPIO_PIN_MASK(clk_pin)); + GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(mosi_port), + GPIO_PIN_MASK(mosi_pin)); + GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(miso_port), + GPIO_PIN_MASK(miso_pin)); + + /* Disable any pull ups or the like */ + ioc_set_over(clk_port, clk_pin, IOC_OVERRIDE_DIS); + ioc_set_over(mosi_port, mosi_pin, IOC_OVERRIDE_DIS); + ioc_set_over(miso_port, miso_pin, IOC_OVERRIDE_DIS); + + /* Configure the clock */ + REG(regs->base + SSI_CPSR) = regs->ssi_cprs_cpsdvsr; + + /* Configure the mode */ + REG(regs->base + SSI_CR0) = mode | (0x07); + + /* Configure the SSI serial clock rate */ + if(!dev->spi_bit_rate) { + scr = 255; + } else { + div = (uint64_t)regs->ssi_cprs_cpsdvsr * dev->spi_bit_rate; + scr = (SSI_SYS_CLOCK + div - 1) / div; + scr = MIN(MAX(scr, 1), 256) - 1; + } + REG(regs->base + SSI_CR0) = (REG(regs->base + SSI_CR0) & ~SSI_CR0_SCR_M) | + scr << SSI_CR0_SCR_S; + + /* Enable the SSI */ + REG(regs->base + SSI_CR1) |= SSI_CR1_SSE; + + return SPI_DEV_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_arch_close_and_unlock(spi_device_t *dev) +{ + if(!spi_arch_has_lock(dev)) { + return SPI_DEV_STATUS_BUS_NOT_OWNED; + } + + /* Disable SSI */ + REG(SYS_CTRL_RCGCSSI) &= ~(1 << dev->spi_controller); + + /* Unlock the SPI bus */ + board_spi_locks_spi[dev->spi_controller].owner = NULL; + mutex_unlock(&board_spi_locks_spi[dev->spi_controller].lock); + + return SPI_DEV_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_arch_select(spi_device_t *dev) +{ + + if(!spi_arch_has_lock(dev)) { + return SPI_DEV_STATUS_BUS_NOT_OWNED; + } + + SPIX_CS_CLR(PIN_TO_PORT(dev->pin_spi_cs), PIN_TO_NUM(dev->pin_spi_cs)); + + return SPI_DEV_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_arch_deselect(spi_device_t *dev) +{ + SPIX_CS_SET(PIN_TO_PORT(dev->pin_spi_cs), PIN_TO_NUM(dev->pin_spi_cs)); + + return SPI_DEV_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +/* Assumes that checking dev and bus is not NULL before calling this */ +spi_status_t +spi_arch_transfer(spi_device_t *dev, + const uint8_t *write_buf, int wlen, + uint8_t *inbuf, int rlen, int ignore_len) +{ + int i; + int totlen; + uint8_t c; + + if(!spi_arch_has_lock(dev)) { + return SPI_DEV_STATUS_BUS_NOT_OWNED; + } + + LOG_DBG("SPI: transfer (r:%d,w:%d) ", rlen, wlen); + + if(write_buf == NULL && wlen > 0) { + return SPI_DEV_STATUS_EINVAL; + } + if(inbuf == NULL && rlen > 0) { + return SPI_DEV_STATUS_EINVAL; + } + + totlen = MAX(rlen + ignore_len, wlen); + + if(totlen == 0) { + /* Nothing to do */ + return SPI_DEV_STATUS_OK; + } + + LOG_DBG_("%c%c%c: %u ", rlen > 0 ? 'R' : '-', wlen > 0 ? 'W' : '-', + ignore_len > 0 ? 'S' : '-', totlen); + + for(i = 0; i < totlen; i++) { + spix_wait_tx_ready(dev); + c = i < wlen ? write_buf[i] : 0; + spix_write_buf(dev, c); + LOG_DBG_("%c%02x->", i < rlen ? ' ' : '#', c); + spix_wait_eotx(dev); + spix_wait_eorx(dev); + c = spix_read_buf(dev); + if(i < rlen) { + inbuf[i] = c; + } + LOG_DBG_("%02x", c); + } + LOG_DBG_("\n"); + + return SPI_DEV_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/cc2538/dev/spi.c b/arch/cpu/cc2538/dev/spi-legacy.c similarity index 99% rename from arch/cpu/cc2538/dev/spi.c rename to arch/cpu/cc2538/dev/spi-legacy.c index a0ced2dad4b931eb80cfcaf897e958c8624da112..0070df6ef7806f8d043a2768f7465b16a44179da 100644 --- a/arch/cpu/cc2538/dev/spi.c +++ b/arch/cpu/cc2538/dev/spi-legacy.c @@ -39,11 +39,11 @@ */ #include "contiki.h" #include "reg.h" -#include "spi-arch.h" +#include "dev/spi-arch-legacy.h" #include "sys/cc.h" #include "dev/ioc.h" #include "dev/sys-ctrl.h" -#include "dev/spi.h" +#include "dev/spi-legacy.h" #include "dev/ssi.h" #include "dev/gpio.h" /*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/cc2538/doxygen-group.txt b/arch/cpu/cc2538/doxygen-group.txt new file mode 100644 index 0000000000000000000000000000000000000000..6e88228b12b484e008749fa55ccd3b0fcf477155 --- /dev/null +++ b/arch/cpu/cc2538/doxygen-group.txt @@ -0,0 +1,14 @@ +/** + * \defgroup cc2538 The TI CC2538 System-on-Chip + * + * CPU-Specific functionality - available to all cc2538-based platforms + * + * \ingroup cpu + */ + +/** + * \defgroup cc2538-platforms TI CC2538-powered platforms + * + * Documentation for all platforms powered by the TI cc2538 System-on-Chip + * \ingroup platform + */ diff --git a/arch/platform/srf06-cc26xx/sensortag/button-sensor.h b/arch/cpu/cc2538/int-master.c similarity index 73% rename from arch/platform/srf06-cc26xx/sensortag/button-sensor.h rename to arch/cpu/cc2538/int-master.c index 1355a585565a6477c3580fcd8a9c1c2b03fba468..57a0316675fbe7f0e0964fa8ac252f332f15fad5 100644 --- a/arch/platform/srf06-cc26xx/sensortag/button-sensor.h +++ b/arch/cpu/cc2538/int-master.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright @@ -29,35 +30,51 @@ */ /*---------------------------------------------------------------------------*/ /** - * \addtogroup sensortag-cc26xx-peripherals + * \addtogroup cc2538 * @{ * - * \defgroup sensortag-cc26xx-button-sensor SensorTag 2.0 Button Sensor + * \defgroup cc2538-interrupts CC2538 master interrupt manipulation + * + * Master interrupt manipulation routines for the CC2538 CPU * - * One of the buttons can be configured as general purpose or as an on/off key * @{ * * \file - * Header file for the Sensortag Button Driver + * Master interrupt manipulation implementation for the TI CC2538 */ /*---------------------------------------------------------------------------*/ -#ifndef BUTTON_SENSOR_H_ -#define BUTTON_SENSOR_H_ -/*---------------------------------------------------------------------------*/ -#include "lib/sensors.h" +#include "contiki.h" +#include "sys/int-master.h" + +#include <stdbool.h> /*---------------------------------------------------------------------------*/ -#define BUTTON_SENSOR "Button" +void +int_master_enable(void) +{ + __enable_irq(); +} /*---------------------------------------------------------------------------*/ -#define BUTTON_SENSOR_VALUE_STATE 0 -#define BUTTON_SENSOR_VALUE_DURATION 1 +int_master_status_t +int_master_read_and_disable(void) +{ + int_master_status_t primask = __get_PRIMASK(); + + __disable_irq(); -#define BUTTON_SENSOR_VALUE_RELEASED 0 -#define BUTTON_SENSOR_VALUE_PRESSED 1 + return primask; +} /*---------------------------------------------------------------------------*/ -extern const struct sensors_sensor button_left_sensor; -extern const struct sensors_sensor button_right_sensor; +void +int_master_status_set(int_master_status_t status) +{ + __set_PRIMASK(status); +} /*---------------------------------------------------------------------------*/ -#endif /* BUTTON_SENSOR_H_ */ +bool +int_master_is_enabled(void) +{ + return __get_PRIMASK() ? false : true; +} /*---------------------------------------------------------------------------*/ /** * @} diff --git a/arch/cpu/cc2538/lpm.c b/arch/cpu/cc2538/lpm.c index 9e21fe4dcca05385285b138831d0cb1cfc6482be..68cb42ae43e519c712622faa954bd1c89266a656 100644 --- a/arch/cpu/cc2538/lpm.c +++ b/arch/cpu/cc2538/lpm.c @@ -61,7 +61,7 @@ #define DEEP_SLEEP_PM1_THRESHOLD 10 #define DEEP_SLEEP_PM2_THRESHOLD 100 /*---------------------------------------------------------------------------*/ -#define assert_wfi() do { asm("wfi"::); } while(0) +#define assert_wfi() do { __asm("wfi"::); } while(0) /*---------------------------------------------------------------------------*/ #if LPM_CONF_STATS rtimer_clock_t lpm_stats[3]; @@ -212,10 +212,14 @@ lpm_exit() /* Restore system clock to the 32 MHz XOSC */ select_32_mhz_xosc(); + if((REG(SYS_CTRL_PMCTL) & SYS_CTRL_PMCTL_PM3) == SYS_CTRL_PMCTL_PM1) { + ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU); + } else { + ENERGEST_SWITCH(ENERGEST_TYPE_DEEP_LPM, ENERGEST_TYPE_CPU); + } + /* Restore PMCTL to PM0 for next pass */ REG(SYS_CTRL_PMCTL) = SYS_CTRL_PMCTL_PM0; - - ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU); } /*---------------------------------------------------------------------------*/ void @@ -286,8 +290,6 @@ lpm_enter() REG(SYS_CTRL_PMCTL) = SYS_CTRL_PMCTL_PM1; } - ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM); - /* Remember the current time so we can keep stats when we wake up */ if(LPM_CONF_STATS) { sleep_enter_time = RTIMER_NOW(); @@ -310,9 +312,13 @@ lpm_enter() REG(SYS_CTRL_PMCTL) = SYS_CTRL_PMCTL_PM0; - ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU); } else { /* All clear. Assert WFI and drop to PM1/2. This is now un-interruptible */ + if((REG(SYS_CTRL_PMCTL) & SYS_CTRL_PMCTL_PM3) == SYS_CTRL_PMCTL_PM1) { + ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM); + } else { + ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_DEEP_LPM); + } assert_wfi(); } diff --git a/arch/cpu/cc2538/rtimer-arch.h b/arch/cpu/cc2538/rtimer-arch.h index 45ebc5c5d915e5d056f774a14bfd20398c60dca0..37aa102da32b8ac30166120afb13549de9aaa5d0 100644 --- a/arch/cpu/cc2538/rtimer-arch.h +++ b/arch/cpu/cc2538/rtimer-arch.h @@ -63,8 +63,6 @@ #include "contiki.h" #include "dev/gptimer.h" -#define RTIMER_ARCH_SECOND 32768 - /* Do the math in 32bits to save precision. * Round to nearest integer rather than truncate. */ #define US_TO_RTIMERTICKS(US) ((US) >= 0 ? \ diff --git a/arch/cpu/cc2538/slip-arch.c b/arch/cpu/cc2538/slip-arch.c index 58aec9f8444c2fa4123964cbce916a4f83c14264..dee023a4fbf7089f1028d7012d3521487e5d23b9 100644 --- a/arch/cpu/cc2538/slip-arch.c +++ b/arch/cpu/cc2538/slip-arch.c @@ -28,21 +28,12 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * \addtogroup cc2538-char-io - * @{ - * - * \file - * Arch-specific SLIP functions for the cc2538 - * - * SLIP can be configured to operate over UART or over USB-Serial, depending - * on the value of SLIP_ARCH_CONF_USB - */ +/*---------------------------------------------------------------------------*/ #include "contiki.h" #include "dev/slip.h" #include "dev/uart.h" #include "usb/usb-serial.h" - +/*---------------------------------------------------------------------------*/ #ifndef SLIP_ARCH_CONF_USB #define SLIP_ARCH_CONF_USB 0 #endif @@ -59,10 +50,6 @@ #define SLIP_END 0300 /*---------------------------------------------------------------------------*/ -/** - * \brief Write a byte over SLIP - * \param c the byte - */ void slip_arch_writeb(unsigned char c) { @@ -72,14 +59,9 @@ slip_arch_writeb(unsigned char c) } } /*---------------------------------------------------------------------------*/ -/** - * \brief Initialise the arch-specific SLIP driver - */ void slip_arch_init() { set_input(slip_input_byte); } /*---------------------------------------------------------------------------*/ - -/** @} */ diff --git a/arch/cpu/cc2538/soc.c b/arch/cpu/cc2538/soc.c index e0ab1a918c0f573fb3a3ac2f76d77f939ca309d6..1aa91009526810553cdb000fc8de74d79a3cfe76 100644 --- a/arch/cpu/cc2538/soc.c +++ b/arch/cpu/cc2538/soc.c @@ -41,6 +41,7 @@ #include "dev/ioc.h" #include "dev/nvic.h" #include "dev/sys-ctrl.h" +#include "dev/gpio-hal.h" #include "lpm.h" #include "reg.h" #include "soc.h" @@ -123,7 +124,7 @@ soc_init() clock_init(); lpm_init(); rtimer_init(); - gpio_init(); + gpio_hal_init(); } /*----------------------------------------------------------------------------*/ /** @} */ diff --git a/arch/cpu/cc2538/startup-gcc.c b/arch/cpu/cc2538/startup-gcc.c index 547764ec343273ad0be9cb945ab44b77c71c4268..bde8d148888c96d94d85cda13a974da67b74d40f 100644 --- a/arch/cpu/cc2538/startup-gcc.c +++ b/arch/cpu/cc2538/startup-gcc.c @@ -52,8 +52,6 @@ void nmi_handler(void); void default_handler(void); /* System Handler and ISR prototypes implemented elsewhere */ -void svcall_handler(void); /* See mtarch.c */ -void pendsv_handler(void); /* See mtarch.c */ void clock_isr(void); /* SysTick Handler */ void gpio_port_a_isr(void); void gpio_port_b_isr(void); @@ -121,10 +119,10 @@ void(*const vectors[])(void) = 0, /* 8 Reserved */ 0, /* 9 Reserved */ 0, /* 10 Reserved */ - svcall_handler, /* 11 SVCall handler */ + default_handler, /* 11 SVCall handler */ default_handler, /* 12 Debug monitor handler */ 0, /* 13 Reserved */ - pendsv_handler, /* 14 The PendSV handler */ + default_handler, /* 14 The PendSV handler */ clock_isr, /* 15 The SysTick handler */ gpio_port_a_isr, /* 16 GPIO Port A */ gpio_port_b_isr, /* 17 GPIO Port B */ diff --git a/arch/cpu/cc2538/usb/cdc-acm-descriptors.c b/arch/cpu/cc2538/usb/cdc-acm-descriptors.c index eb2a9d7b35a0a80c51073678627ea62a08b13b35..fd56ed30318bdf262521d6ca39e4d7fe32c0f127 100644 --- a/arch/cpu/cc2538/usb/cdc-acm-descriptors.c +++ b/arch/cpu/cc2538/usb/cdc-acm-descriptors.c @@ -161,7 +161,7 @@ const struct configuration_st { }; -const struct usb_st_configuration_descriptor const *configuration_head = -(struct usb_st_configuration_descriptor const *)&configuration_block; +const struct usb_st_configuration_descriptor* const configuration_head = +(const struct usb_st_configuration_descriptor*)&configuration_block; /** @} */ diff --git a/arch/cpu/cc2538/usb/common/descriptors.h b/arch/cpu/cc2538/usb/common/descriptors.h index f5418439570fa53c67ef77bdfac7ac85c82aeea6..6c89f3c038c868d6a704e4a2c676cc7d430468be 100644 --- a/arch/cpu/cc2538/usb/common/descriptors.h +++ b/arch/cpu/cc2538/usb/common/descriptors.h @@ -6,5 +6,5 @@ #endif extern const struct usb_st_device_descriptor device_descriptor; -extern const struct usb_st_configuration_descriptor const *configuration_head; +extern const struct usb_st_configuration_descriptor* const configuration_head; #endif /* DESCRIPTORS_H_RPFUB8O7OV__ */ diff --git a/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx b/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx index f976eb85bc3a4144229bd6e6c52fb1ab4b2b0145..e72954c17a780f1295e2ec9ad973b055805b46af 100644 --- a/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx +++ b/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx @@ -1,13 +1,3 @@ -CC = arm-none-eabi-gcc -CPP = arm-none-eabi-cpp -LD = arm-none-eabi-gcc -AR = arm-none-eabi-ar -OBJCOPY = arm-none-eabi-objcopy -OBJDUMP = arm-none-eabi-objdump -NM = arm-none-eabi-nm -SIZE = arm-none-eabi-size -SREC_CAT = srec_cat - CPU_ABS_PATH = arch/cpu/cc26xx-cc13xx TI_XXWARE = $(CONTIKI_CPU)/$(TI_XXWARE_PATH) @@ -29,59 +19,30 @@ MODULES += $(TI_XXWARE_SRC) LDSCRIPT = $(CONTIKI_CPU)/cc26xx.ld -CFLAGS += -mcpu=cortex-m3 -mthumb -mlittle-endian -CFLAGS += -ffunction-sections -fdata-sections -CFLAGS += -fshort-enums -fomit-frame-pointer -fno-strict-aliasing -CFLAGS += -Wall -std=c99 - -LDFLAGS += -mcpu=cortex-m3 -mthumb -mlittle-endian -nostartfiles -LDFLAGS += -T $(LDSCRIPT) -LDFLAGS += -Wl,--gc-sections,--sort-section=alignment -LDFLAGS += -Wl,-Map=$(@:.elf=-$(TARGET).map),--cref,--no-warn-mismatch -OBJCOPY_FLAGS += -O binary --gap-fill 0xff -OBJDUMP_FLAGS += --disassemble --source --disassembler-options=force-thumb - -ifeq ($(WERROR),1) -CFLAGS += -Werror -endif - -### Are we building with code size optimisations? -SMALL ?= 1 -ifeq ($(SMALL),1) - CFLAGS += -Os -else - CFLAGS += -O2 -endif - ### If the user-specified a Node ID, pass a define ifdef NODEID CFLAGS += -DIEEE_ADDR_NODE_ID=$(NODEID) endif -### CPU-dependent cleanup files -CLEAN += *.d *.elf *.hex - ### CPU-dependent directories -CONTIKI_CPU_DIRS = . dev rf-core rf-core/api $(TI_XXWARE_STARTUP_DIR) - -### Use the existing debug I/O in arch/cpu/arm/common -CONTIKI_CPU_DIRS += ../arm/common/dbg-io +CONTIKI_CPU_DIRS += . dev rf-core rf-core/api rf-core/ble-hal $(TI_XXWARE_STARTUP_DIR) ### CPU-dependent source files CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c soc-rtc.c uart.c CONTIKI_CPU_SOURCEFILES += contiki-watchdog.c aux-ctrl.c -CONTIKI_CPU_SOURCEFILES += putchar.c ieee-addr.c batmon-sensor.c adc-sensor.c +CONTIKI_CPU_SOURCEFILES += dbg.c ieee-addr.c batmon-sensor.c adc-sensor.c CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c cc26xx-uart.c lpm.c -CONTIKI_CPU_SOURCEFILES += gpio-interrupt.c oscillators.c +CONTIKI_CPU_SOURCEFILES += gpio-interrupt.c gpio-hal-arch.c oscillators.c CONTIKI_CPU_SOURCEFILES += rf-core.c rf-ble.c ieee-mode.c -CONTIKI_CPU_SOURCEFILES += random.c soc-trng.c +CONTIKI_CPU_SOURCEFILES += ble-cc2650.c ble-hal-cc26xx.c ble-addr.c rf-ble-cmd.c +CONTIKI_CPU_SOURCEFILES += random.c soc-trng.c int-master.c +CONTIKI_CPU_SOURCEFILES += spi-arch.c -DEBUG_IO_SOURCEFILES += dbg-printf.c dbg-snprintf.c dbg-sprintf.c strformat.c +MODULES += os/lib/dbg-io -CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) $(DEBUG_IO_SOURCEFILES) +CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) -TARGET_START_SOURCEFILES += fault-handlers.c $(TI_XXWARE_STARTUP_SRCS) -TARGET_STARTFILES = $(addprefix $(OBJECTDIR)/,$(call oname, $(TARGET_START_SOURCEFILES))) +CPU_START_SOURCEFILES += fault-handlers.c $(TI_XXWARE_STARTUP_SRCS) PYTHON = python BSL_FLAGS += -e -w -v @@ -92,9 +53,6 @@ endif BSL = $(CONTIKI)/tools/cc2538-bsl/cc2538-bsl.py -### Don't treat the .elf as intermediate -.PRECIOUS: %.elf %.hex %.bin - ### Always re-build ieee-addr.o in case the command line passes a new NODEID FORCE: @@ -106,31 +64,7 @@ $(OBJECTDIR)/ieee-addr.o: ieee-addr.c FORCE | $(OBJECTDIR) ### to make clean first $(OBJECTDIR)/ccfg.o: ccfg.c FORCE | $(OBJECTDIR) $(TRACE_CC) - $(Q)$(CC) $(CFLAGS) -include "contiki-conf.h" -c $< -o $@ - -### Compilation rules -CUSTOM_RULE_LINK=1 - -%.elf: $(TARGET_STARTFILES) %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(LDSCRIPT) - $(TRACE_LD) - $(Q)$(LD) $(LDFLAGS) ${filter-out $(LDSCRIPT) %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -lm -o $@ - -%.i16hex: %.elf - $(OBJCOPY) -O ihex $< $@ - -%.hex: %.i16hex - $(SREC_CAT) $< -intel -o $@ -intel - -%.bin: %.elf - $(OBJCOPY) $(OBJCOPY_FLAGS) $< $@ - -%.lst: %.elf - $(OBJDUMP) $(OBJDUMP_FLAGS) $< > $@ - -### We don't really need the .hex and .bin for the .$(TARGET) but let's make -### sure they get built -%.$(TARGET): %.elf %.hex %.bin - cp $< $@ + $(Q)$(CC) $(CFLAGS) -include "ccxxware-conf.h" -c $< -o $@ # a target that gives a user-friendly memory profile, taking into account the RAM # that is statically occupied by the stack as defined in the linker script @@ -170,3 +104,5 @@ UART_BAUDRATE = 115200 login: $(SERIALDUMP) -b$(UART_BAUDRATE) $(PORT) + +include $(CONTIKI)/arch/cpu/arm/cortex-m/cm3/Makefile.cm3 diff --git a/arch/cpu/cc26xx-cc13xx/ble-addr.c b/arch/cpu/cc26xx-cc13xx/ble-addr.c new file mode 100644 index 0000000000000000000000000000000000000000..7617133ccea87d6aacf56a0715f5ea0b61875051 --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/ble-addr.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016, Michael Spoerk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * \file + * Driver for the retrieval of an BLE address from flash + * + * \author + * Michael Spoerk <mi.spoerk@gmail.com> + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "net/linkaddr.h" +#include <string.h> + +#include "ble-addr.h" +#include "os/dev/ble-hal.h" +/*---------------------------------------------------------------------------*/ +void +ble_addr_cpy_to(uint8_t *dst) +{ + int i; + uint8_t *location = (uint8_t *)BLE_ADDR_LOCATION; + + for(i = 0; i < BLE_ADDR_SIZE; i++) { + dst[i] = location[BLE_ADDR_SIZE - 1 - i]; + } +} +/*---------------------------------------------------------------------------*/ +void +ble_addr_to_eui64(uint8_t *dst, uint8_t *src) +{ + memcpy(dst, src, 3); + dst[3] = 0xFF; + dst[4] = 0xFE; + memcpy(&dst[5], &src[3], 3); +} +/*---------------------------------------------------------------------------*/ +void +ble_eui64_addr_cpy_to(uint8_t *dst) +{ + uint8_t ble_addr[BLE_ADDR_SIZE]; + ble_addr_cpy_to(ble_addr); + ble_addr_to_eui64(dst, ble_addr); +} diff --git a/arch/cpu/cc26xx-cc13xx/ble-addr.h b/arch/cpu/cc26xx-cc13xx/ble-addr.h new file mode 100644 index 0000000000000000000000000000000000000000..4f61b0dd6b82d969b9599f76bb803299e98dfdda --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/ble-addr.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016, Michael Spoerk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * \file + * Driver for the retrieval of an BLE address from flash + * + * \author + * Michael Spoerk <mi.spoerk@gmail.com> + */ +/*---------------------------------------------------------------------------*/ +#ifndef BLE_ADDR_H_ +#define BLE_ADDR_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include <stdint.h> +/*---------------------------------------------------------------------------*/ +/* primary BLE address location */ +#define BLE_ADDR_LOCATION 0x500012E8 + +/*---------------------------------------------------------------------------*/ +/** + * \brief Copy the node's factory BLE address to a destination memory area + * \param dst A pointer to the destination area where the BLE address is to be + * written + * + * This function will copy 6 bytes and it will invert byte order in + * the process. The factory address on devices is normally little-endian, + * therefore you should expect dst to store the address in a big-endian order. + */ +void ble_addr_cpy_to(uint8_t *dst); + +/*---------------------------------------------------------------------------*/ +/** + * \brief Copy the node's BLE address to a destination memory area and converts + * it into a EUI64 address in the process + * \param dst A pointer to the destination area where the EUI64 address is to be + * written + * \param src A pointer to the BLE address that is to be copied + */ +void ble_addr_to_eui64(uint8_t *dst, uint8_t *src); + +/*---------------------------------------------------------------------------*/ +/** + * \brief Copy the node's EUI64 address that is based on its factory BLE address + * to a destination memory area + * \param dst A pointer to the destination area where the EUI64 address is to be + * written + */ +void ble_eui64_addr_cpy_to(uint8_t *dst); +/*---------------------------------------------------------------------------*/ + +#endif /* BLE_ADDR_H_ */ diff --git a/arch/cpu/cc26xx-cc13xx/cc13x0-cc26x0-cm3.h b/arch/cpu/cc26xx-cc13xx/cc13x0-cc26x0-cm3.h new file mode 100644 index 0000000000000000000000000000000000000000..bda2e2b07de1e7775d17de0eb10f4f8842a1c6cd --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/cc13x0-cc26x0-cm3.h @@ -0,0 +1,128 @@ +/* + * Template: + * Copyright (c) 2012 ARM LIMITED + * All rights reserved. + * + * CC13xx-CC26xx: + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc26xx + * @{ + * + * \defgroup cc26xx-cm3 CC13xx/CC26xx CMSIS + * + * CC13xx/CC26xx Cortex-M3 CMSIS definitions + * @{ + * + * \file + * CMSIS Cortex-M3 core peripheral access layer header file for CC13xx/CC26xx + */ +/*---------------------------------------------------------------------------*/ +#ifndef CC13XX_CC26XX_CM3_H_ +#define CC13XX_CC26XX_CM3_H_ +/*---------------------------------------------------------------------------*/ +/** + * \name Interrupt Number Definition + * @{ + */ +typedef enum cc13xx_cc26xx_cm3_irq_e { + /* Cortex-M3 Processor Exceptions */ + CC13XX_CC26XX_CM3_EXCEPTION_RESET = -15, /**< 1 Reset */ + CC13XX_CC26XX_CM3_EXCEPTION_NMI = -14, /**< 2 NMI */ + CC13XX_CC26XX_CM3_EXCEPTION_HARD_FAULT = -13, /**< 3 Hard fault */ + CC13XX_CC26XX_CM3_EXCEPTION_MPU_FAULT = -12, /**< 4 MPU fault */ + CC13XX_CC26XX_CM3_EXCEPTION_BUS_FAULT = -11, /**< 5 Bus fault */ + CC13XX_CC26XX_CM3_EXCEPTION_USAGE_FAULT = -10, /**< 6 Usage fault */ + CC13XX_CC26XX_CM3_EXCEPTION_SV_CALL = -5, /**< 11 SVCall */ + CC13XX_CC26XX_CM3_EXCEPTION_DEBUG_MON = -4, /**< 12 Debug monitor */ + CC13XX_CC26XX_CM3_EXCEPTION_PEND_SV = -2, /**< 14 PendSV */ + CC13XX_CC26XX_CM3_EXCEPTION_SYS_TICK = -1, /**< 15 SysTick */ + + /* CC13xx/CC26xx interrupts */ + CC13XX_CC26XX_CM3_IRQ_EDGE_DETECT = 0, /**< 16 AON edge detect */ + CC13XX_CC26XX_CM3_EXCEPTION_I2C = 1, /**< 17 I2C */ + CC13XX_CC26XX_CM3_EXCEPTION_RF_CPE1 = 2, /**< 18 RF Command and Packet Engine 1 */ + CC13XX_CC26XX_CM3_EXCEPTION_AON_SPI_SLAVE = 3, /**< 19 AON SpiSplave Rx, Tx and CS */ + CC13XX_CC26XX_CM3_EXCEPTION_AON_RTC = 4, /**< 20 AON RTC */ + CC13XX_CC26XX_CM3_EXCEPTION_UART0 = 5, /**< 21 UART0 Rx and Tx */ + CC13XX_CC26XX_CM3_EXCEPTION_AON_AUX_SWEV0 = 6, /**< 22 Sensor Controller software event 0, through AON domain*/ + CC13XX_CC26XX_CM3_EXCEPTION_SSI0 = 7, /**< 23 SSI0 Rx and Tx */ + CC13XX_CC26XX_CM3_EXCEPTION_SSI1 = 8, /**< 24 SSI1 Rx and Tx */ + CC13XX_CC26XX_CM3_EXCEPTION_RF_CPE0 = 9, /**< 25 RF Command and Packet Engine 0 */ + CC13XX_CC26XX_CM3_EXCEPTION_RF_HW = 10, /**< 26 RF Core Hardware */ + CC13XX_CC26XX_CM3_EXCEPTION_RF_CMD_ACK = 11, /**< 27 RF Core Command Acknowledge */ + CC13XX_CC26XX_CM3_EXCEPTION_I2S = 12, /**< 28 I2S */ + CC13XX_CC26XX_CM3_EXCEPTION_AON_AUX_SWEV1 = 13, /**< 29 Sensor Controller software event 1, through AON domain*/ + CC13XX_CC26XX_CM3_EXCEPTION_WATCHDOG = 14, /**< 30 Watchdog timer */ + CC13XX_CC26XX_CM3_EXCEPTION_GPTIMER_0A = 15, /**< 31 Timer 0 subtimer A */ + CC13XX_CC26XX_CM3_EXCEPTION_GPTIMER_0B = 16, /**< 32 Timer 0 subtimer B */ + CC13XX_CC26XX_CM3_EXCEPTION_GPTIMER_1A = 17, /**< 33 Timer 1 subtimer A */ + CC13XX_CC26XX_CM3_EXCEPTION_GPTIMER_1B = 18, /**< 34 Timer 1 subtimer B */ + CC13XX_CC26XX_CM3_EXCEPTION_GPTIMER_2A = 19, /**< 35 Timer 2 subtimer A */ + CC13XX_CC26XX_CM3_EXCEPTION_GPTIMER_2B = 20, /**< 36 Timer 2 subtimer B */ + CC13XX_CC26XX_CM3_EXCEPTION_GPTIMER_3A = 21, /**< 37 Timer 3 subtimer A */ + CC13XX_CC26XX_CM3_EXCEPTION_GPTIMER_3B = 22, /**< 38 Timer 3 subtimer B */ + CC13XX_CC26XX_CM3_EXCEPTION_CRYPTO = 23, /**< 39 Crypto Core Result available */ + CC13XX_CC26XX_CM3_EXCEPTION_UDMA = 24, /**< 40 uDMA Software */ + CC13XX_CC26XX_CM3_EXCEPTION_UDMA_ERR = 25, /**< 41 uDMA Error */ + CC13XX_CC26XX_CM3_EXCEPTION_FLASH_CTRL = 26, /**< 42 Flash controller */ + CC13XX_CC26XX_CM3_EXCEPTION_SW0 = 27, /**< 43 Software Event 0 */ + CC13XX_CC26XX_CM3_EXCEPTION_AUX_COM_EVENT = 28, /**< 44 AUX combined event, directly to MCU domain*/ + CC13XX_CC26XX_CM3_EXCEPTION_AON_PRG0 = 29, /**< 45 AON programmable 0 */ + CC13XX_CC26XX_CM3_EXCEPTION_PROG = 30, /**< 46 Dynamic Programmable interrupt (default source: PRCM)*/ + CC13XX_CC26XX_CM3_EXCEPTION_AUX_COMPA = 31, /**< 47 AUX Comparator A */ + CC13XX_CC26XX_CM3_EXCEPTION_AUX_ADC = 32, /**< 48 AUX ADC IRQ */ + CC13XX_CC26XX_CM3_EXCEPTION_TRNG = 33, /**< 49 TRNG event */ +} cc13xx_cc26xx_cm3_irq_t; + +typedef cc13xx_cc26xx_cm3_irq_t IRQn_Type; + +#define SysTick_IRQn CC13XX_CC26XX_CM3_EXCEPTION_SYS_TICK +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name Processor and Core Peripheral Section + * @{ + */ +/* Configuration of the Cortex-M3 Processor and Core Peripherals */ +#define __MPU_PRESENT 1 /**< MPU present or not */ +#define __NVIC_PRIO_BITS 3 /**< Number of Bits used for Priority Levels */ +#define __Vendor_SysTickConfig 0 /**< Set to 1 if different SysTick Config is used */ +/** @} */ +/*---------------------------------------------------------------------------*/ +#include "core_cm3.h" /* Cortex-M3 processor and core peripherals */ +/*---------------------------------------------------------------------------*/ +#endif /* CC13XX_CC26XX_CM3_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-conf.h b/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-conf.h new file mode 100644 index 0000000000000000000000000000000000000000..83519f795ae428e1ed2362a27fcf3b9ddc00e1f7 --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-conf.h @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc26xx + * @{ + * + * \file + * Header with configuration defines common to all CC13xx/CC26xx platforms + */ +/*---------------------------------------------------------------------------*/ +#ifndef CC13XX_CC26XX_CONF_H_ +#define CC13XX_CC26XX_CONF_H_ +/*---------------------------------------------------------------------------*/ +/** + * \name Network Stack Configuration + * + * @{ + */ + +/* + * If set, the systems keeps the HF crystal oscillator on even when the radio is off. + * You need to set this to 1 to use TSCH with its default 2.2ms or larger guard time. + */ +#ifndef CC2650_FAST_RADIO_STARTUP +#define CC2650_FAST_RADIO_STARTUP (MAC_CONF_WITH_TSCH) +#endif + +#ifdef RF_CHANNEL +#define RF_CORE_CONF_CHANNEL RF_CHANNEL +#endif + +#ifndef RF_CORE_CONF_CHANNEL +#define RF_CORE_CONF_CHANNEL 25 +#endif + +/* Number of Prop Mode RX buffers */ +#ifndef PROP_MODE_CONF_RX_BUF_CNT +#define PROP_MODE_CONF_RX_BUF_CNT 4 +#endif + +/* + * Auto-configure Prop-mode radio if we are running on CC13xx, unless the + * project has specified otherwise. Depending on the final mode, determine a + * default channel (again, if unspecified) and configure RDC params + */ +#if CPU_FAMILY_CC13XX +#ifndef CC13XX_CONF_PROP_MODE +#define CC13XX_CONF_PROP_MODE 1 +#endif /* CC13XX_CONF_PROP_MODE */ +#endif /* CPU_FAMILY_CC13XX */ + +#if CC13XX_CONF_PROP_MODE +#define NETSTACK_CONF_RADIO prop_mode_driver + +#ifndef RF_CORE_CONF_CHANNEL +#define RF_CORE_CONF_CHANNEL 0 +#endif + +#define CSMA_CONF_ACK_WAIT_TIME (RTIMER_SECOND / 400) +#define CSMA_CONF_AFTER_ACK_DETECTED_WAIT_TIME (RTIMER_SECOND / 1000) +#define CSMA_CONF_SEND_SOFT_ACK 1 + +#else /* CC13XX_CONF_PROP_MODE */ +#ifndef NETSTACK_CONF_RADIO +#define NETSTACK_CONF_RADIO ieee_mode_driver +#endif + +#define CSMA_CONF_SEND_SOFT_ACK 0 +#endif /* CC13XX_CONF_PROP_MODE */ + +#define NETSTACK_RADIO_MAX_PAYLOAD_LEN 125 + +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name IEEE address configuration + * + * Used to generate our link-local & IPv6 address + * @{ + */ +/** + * \brief Location of the IEEE address + * 0 => Read from InfoPage, + * 1 => Use a hardcoded address, configured by IEEE_ADDR_CONF_ADDRESS + */ +#ifndef IEEE_ADDR_CONF_HARDCODED +#define IEEE_ADDR_CONF_HARDCODED 0 +#endif + +/** + * \brief The hardcoded IEEE address to be used when IEEE_ADDR_CONF_HARDCODED + * is defined as 1 + */ +#ifndef IEEE_ADDR_CONF_ADDRESS +#define IEEE_ADDR_CONF_ADDRESS { 0x00, 0x12, 0x4B, 0x00, 0x89, 0xAB, 0xCD, 0xEF } +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name RF configuration + * + * @{ + */ +/* RF Config */ + +#ifndef IEEE_MODE_CONF_AUTOACK +#define IEEE_MODE_CONF_AUTOACK 1 /**< RF H/W generates ACKs */ +#endif + +#ifndef IEEE_MODE_CONF_PROMISCOUS +#define IEEE_MODE_CONF_PROMISCOUS 0 /**< 1 to enable promiscous mode */ +#endif + +#ifndef RF_BLE_CONF_ENABLED +#define RF_BLE_CONF_ENABLED 0 /**< 0 to disable BLE support */ +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Character I/O Configuration + * + * @{ + */ +#ifndef CC26XX_UART_CONF_ENABLE +#define CC26XX_UART_CONF_ENABLE 1 /**< Enable/Disable UART I/O */ +#endif + +#ifndef CC26XX_UART_CONF_BAUD_RATE +#define CC26XX_UART_CONF_BAUD_RATE 115200 /**< Default UART0 baud rate */ +#endif + +/* Enable I/O over the Debugger Devpack - Only relevant for the SensorTag */ +#ifndef BOARD_CONF_DEBUGGER_DEVPACK +#define BOARD_CONF_DEBUGGER_DEVPACK 1 +#endif + +#ifndef SLIP_ARCH_CONF_ENABLED +/* + * Determine whether we need SLIP + * This will keep working while UIP_FALLBACK_INTERFACE and CMD_CONF_OUTPUT + * keep using SLIP + */ +#if defined(UIP_FALLBACK_INTERFACE) || defined(CMD_CONF_OUTPUT) +#define SLIP_ARCH_CONF_ENABLED 1 +#endif +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name JTAG interface configuration + * + * Enable/Disable the JTAG DAP and TAP interfaces on the chip. + * Setting this to 0 will disable access to the debug interface + * to secure deployed images. + * @{ + */ +#ifndef CCXXWARE_CONF_JTAG_INTERFACE_ENABLE +#define CCXXWARE_CONF_JTAG_INTERFACE_ENABLE 1 +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name ROM Bootloader configuration + * + * Enable/Disable the ROM bootloader in your image, if the board supports it. + * Look in board.h to choose the DIO and corresponding level that will cause + * the chip to enter bootloader mode. + * @{ + */ +#ifndef ROM_BOOTLOADER_ENABLE +#define ROM_BOOTLOADER_ENABLE 0 +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +#endif /* CC13XX_CC26XX_CONF_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-def.h b/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-def.h new file mode 100644 index 0000000000000000000000000000000000000000..15db03448062c2c0544879633cc2b03e3945d450 --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-def.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#ifndef CC13XX_CC26XX_DEF_H_ +#define CC13XX_CC26XX_DEF_H_ +/*---------------------------------------------------------------------------*/ +#include "cm3/cm3-def.h" +/*---------------------------------------------------------------------------*/ +/* TSCH related defines */ + +/* Delay between GO signal and SFD */ +#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(81)) +/* Delay between GO signal and start listening. + * This value is so small because the radio is constantly on within each timeslot. */ +#define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(15)) +/* Delay between the SFD finishes arriving and it is detected in software. */ +#define RADIO_DELAY_BEFORE_DETECT ((unsigned)US_TO_RTIMERTICKS(352)) + +/* Timer conversion; radio is running at 4 MHz */ +#define RADIO_TIMER_SECOND 4000000u +#if (RTIMER_SECOND % 256) || (RADIO_TIMER_SECOND % 256) +#error RADIO_TO_RTIMER macro must be fixed! +#endif +#define RADIO_TO_RTIMER(X) ((uint32_t)(((uint64_t)(X) * (RTIMER_SECOND / 256)) / (RADIO_TIMER_SECOND / 256))) +#define USEC_TO_RADIO(X) ((X) * 4) + +/* The PHY header (preamble + SFD, 4+1 bytes) duration is equivalent to 10 symbols */ +#define RADIO_IEEE_802154_PHY_HEADER_DURATION_USEC 160 + +/* Do not turn off TSCH within a timeslot: not enough time */ +#define TSCH_CONF_RADIO_ON_DURING_TIMESLOT 1 + +/* Disable TSCH frame filtering */ +#define TSCH_CONF_HW_FRAME_FILTERING 0 + +/* Use hardware timestamps */ +#ifndef TSCH_CONF_RESYNC_WITH_SFD_TIMESTAMPS +#define TSCH_CONF_RESYNC_WITH_SFD_TIMESTAMPS 1 +#define TSCH_CONF_TIMESYNC_REMOVE_JITTER 0 +#endif + +#ifndef TSCH_CONF_BASE_DRIFT_PPM +/* The drift compared to "true" 10ms slots. + * Enable adaptive sync to enable compensation for this. + * Slot length 10000 usec + * 328 ticks + * Tick duration 30.517578125 usec + * Real slot duration 10009.765625 usec + * Target - real duration = -9.765625 usec + * TSCH_CONF_BASE_DRIFT_PPM -977 + */ +#define TSCH_CONF_BASE_DRIFT_PPM -977 +#endif + +/* 10 times per second */ +#ifndef TSCH_CONF_CHANNEL_SCAN_DURATION +#define TSCH_CONF_CHANNEL_SCAN_DURATION (CLOCK_SECOND / 10) +#endif + +/* Slightly reduce the TSCH guard time (from 2200 usec to 1800 usec) to make sure + * the CC26xx radio has sufficient time to start up. */ +#ifndef TSCH_CONF_RX_WAIT +#define TSCH_CONF_RX_WAIT 1800 +#endif +/*---------------------------------------------------------------------------*/ +#define RTIMER_ARCH_SECOND 65536 +/*---------------------------------------------------------------------------*/ +/* Path to CMSIS header */ +#define CMSIS_CONF_HEADER_PATH "cc13x0-cc26x0-cm3.h" + +/* Path to headers with implementation of mutexes and memory barriers */ +#define MUTEX_CONF_ARCH_HEADER_PATH "mutex-cortex.h" +#define MEMORY_BARRIER_CONF_ARCH_HEADER_PATH "memory-barrier-cortex.h" + +#define GPIO_HAL_CONF_ARCH_HDR_PATH "dev/gpio-hal-arch.h" +/*---------------------------------------------------------------------------*/ +#define GPIO_HAL_CONF_ARCH_SW_TOGGLE 0 +/*---------------------------------------------------------------------------*/ +#define SPI_CONF_CONTROLLER_COUNT 2 +/*---------------------------------------------------------------------------*/ +#endif /* CC13XX_CC26XX_DEF_H_ */ +/*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/cc26xx-cc13xx/cc26xx.ld b/arch/cpu/cc26xx-cc13xx/cc26xx.ld index 84601ced63a514f52e61b26ec6ff6821c9ae0020..46ecf1322ede0ce867de45ed20a666e3715dc853 100644 --- a/arch/cpu/cc26xx-cc13xx/cc26xx.ld +++ b/arch/cpu/cc26xx-cc13xx/cc26xx.ld @@ -56,7 +56,7 @@ _estack = ORIGIN(SRAM) + LENGTH(SRAM); /* End of SRAM */ /*. Generate a link error if heap and stack don’t fit into RAM .*/ _Min_Heap_Size = 0; -_Min_Stack_Size = 0x100; +_Min_Stack_Size = 0x400; SECTIONS { @@ -90,6 +90,12 @@ SECTIONS _ebss = .; } > SRAM + _end = .; /* End of the .bss segment. */ + + /* These symbols are used by the stack check library. */ + _stack = .; + _stack_origin = ORIGIN(SRAM) + LENGTH(SRAM); + .ccfg : { KEEP(*(.ccfg)) diff --git a/arch/cpu/cc26xx-cc13xx/ccxxware-conf.h b/arch/cpu/cc26xx-cc13xx/ccxxware-conf.h new file mode 100644 index 0000000000000000000000000000000000000000..97be16b5d77b0e29372f2a5d84405020e45a0269 --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/ccxxware-conf.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017, Alex Stanoev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup cc26xx + * @{ + * + * \defgroup cc26xx-ccxxware-conf CCxxware-specific configuration + * + * @{ + * + * \file + * CCxxware-specific configuration for the cc26xx-cc13xx CPU family + */ +#ifndef CCXXWARE_CONF_H_ +#define CCXXWARE_CONF_H_ + +#include "contiki-conf.h" + +/*---------------------------------------------------------------------------*/ +/** + * \brief JTAG interface configuration + * + * Those values are not meant to be modified by the user + * @{ + */ +#if CCXXWARE_CONF_JTAG_INTERFACE_ENABLE +#define SET_CCFG_CCFG_TI_OPTIONS_TI_FA_ENABLE 0xC5 +#define SET_CCFG_CCFG_TAP_DAP_0_CPU_DAP_ENABLE 0xC5 +#define SET_CCFG_CCFG_TAP_DAP_0_PRCM_TAP_ENABLE 0xC5 +#define SET_CCFG_CCFG_TAP_DAP_0_TEST_TAP_ENABLE 0xC5 +#define SET_CCFG_CCFG_TAP_DAP_1_PBIST2_TAP_ENABLE 0xC5 +#define SET_CCFG_CCFG_TAP_DAP_1_PBIST1_TAP_ENABLE 0xC5 +#define SET_CCFG_CCFG_TAP_DAP_1_WUC_TAP_ENABLE 0xC5 +#else +#define SET_CCFG_CCFG_TI_OPTIONS_TI_FA_ENABLE 0x00 +#define SET_CCFG_CCFG_TAP_DAP_0_CPU_DAP_ENABLE 0x00 +#define SET_CCFG_CCFG_TAP_DAP_0_PRCM_TAP_ENABLE 0x00 +#define SET_CCFG_CCFG_TAP_DAP_0_TEST_TAP_ENABLE 0x00 +#define SET_CCFG_CCFG_TAP_DAP_1_PBIST2_TAP_ENABLE 0x00 +#define SET_CCFG_CCFG_TAP_DAP_1_PBIST1_TAP_ENABLE 0x00 +#define SET_CCFG_CCFG_TAP_DAP_1_WUC_TAP_ENABLE 0x00 +#endif +/** @} */ +#endif /* CCXXWARE_CONF_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/arch/cpu/cc26xx-cc13xx/clock.c b/arch/cpu/cc26xx-cc13xx/clock.c index 98d18e653e13b419f1c051df519568ff58d1d0fc..172d1c3fd967b33c8c099f7f49cf1830c5e0be10 100644 --- a/arch/cpu/cc26xx-cc13xx/clock.c +++ b/arch/cpu/cc26xx-cc13xx/clock.c @@ -29,22 +29,6 @@ */ /*---------------------------------------------------------------------------*/ /** - * \addtogroup platform - * @{ - * - * \defgroup cc26xx-platforms TI CC26xx-powered platforms - * @{ - * - * \defgroup cc26xx The TI CC26xx and CC13xx CPUs - * - * This group documents the TI CC26xx and CC13xx CPUs. The two CPU families are - * very similar, with the main difference being related to radio capability. - * - * Documentation in this group should be considered to be applicable to both - * families, unless explicitly stated otherwise. - * - * @{ - * * \addtogroup cc26xx-clocks * @{ * @@ -140,7 +124,7 @@ update_clock_variable(void) count = (aon_rtc_secs_now * CLOCK_SECOND) + (aon_rtc_ticks_now >> 9); } /*---------------------------------------------------------------------------*/ -CCIF clock_time_t +clock_time_t clock_time(void) { update_clock_variable(); @@ -158,7 +142,7 @@ clock_update(void) } } /*---------------------------------------------------------------------------*/ -CCIF unsigned long +unsigned long clock_seconds(void) { bool interrupts_disabled; @@ -228,9 +212,6 @@ clock_delay(unsigned int i) } /*---------------------------------------------------------------------------*/ /** - * @} - * @} - * @} * @} * @} */ diff --git a/arch/cpu/cc26xx-cc13xx/putchar.c b/arch/cpu/cc26xx-cc13xx/dbg.c similarity index 84% rename from arch/cpu/cc26xx-cc13xx/putchar.c rename to arch/cpu/cc26xx-cc13xx/dbg.c index 7cbd1901a7124d103818bf7136c608db4a20beaf..bf03aade4fe154043e4a648952afb531c9fbd131 100644 --- a/arch/cpu/cc26xx-cc13xx/putchar.c +++ b/arch/cpu/cc26xx-cc13xx/dbg.c @@ -34,33 +34,12 @@ #include <string.h> /*---------------------------------------------------------------------------*/ int -putchar(int c) +dbg_putchar(int c) { cc26xx_uart_write_byte(c); return c; } /*---------------------------------------------------------------------------*/ -int -puts(const char *str) -{ - int i; - if(str == NULL) { - return 0; - } - for(i = 0; i < strlen(str); i++) { - cc26xx_uart_write_byte(str[i]); - } - cc26xx_uart_write_byte('\n'); - - /* - * Wait for the line to go out. This is to prevent garbage when used between - * UART on/off cycles - */ - while(cc26xx_uart_busy() == UART_BUSY); - - return i; -} -/*---------------------------------------------------------------------------*/ unsigned int dbg_send_bytes(const unsigned char *s, unsigned int len) { diff --git a/arch/cpu/cc26xx-cc13xx/dev/adc-sensor.c b/arch/cpu/cc26xx-cc13xx/dev/adc-sensor.c index 1f736bb53997ef29d116df4dc703da87a4be6df0..c88b2e5fe983c32bda81c8168ba455f76cdb68ac 100644 --- a/arch/cpu/cc26xx-cc13xx/dev/adc-sensor.c +++ b/arch/cpu/cc26xx-cc13xx/dev/adc-sensor.c @@ -39,7 +39,6 @@ #include "contiki.h" #include "lib/sensors.h" #include "dev/adc-sensor.h" -#include "gpio-interrupt.h" #include "sys/timer.h" #include "lpm.h" diff --git a/arch/cpu/cc26xx-cc13xx/dev/batmon-sensor.h b/arch/cpu/cc26xx-cc13xx/dev/batmon-sensor.h index 014e9a17de3759a113f80683fb0af154b6ac02ed..cde7abc8e0865dce551886c62eaf8829b848b633 100644 --- a/arch/cpu/cc26xx-cc13xx/dev/batmon-sensor.h +++ b/arch/cpu/cc26xx-cc13xx/dev/batmon-sensor.h @@ -44,6 +44,9 @@ #ifndef BATMON_SENSOR_H_ #define BATMON_SENSOR_H_ /*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ #define BATMON_SENSOR_TYPE_TEMP 1 #define BATMON_SENSOR_TYPE_VOLT 2 /*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.c b/arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.c new file mode 100644 index 0000000000000000000000000000000000000000..a7b025800d2fe1986dd8aaf26909a61068f2e739 --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc26xx-gpio-hal + * @{ + * + * \file + * Implementation file for the CC13xx/CC26xx GPIO HAL functions + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "ti-lib.h" +#include "ti-lib-rom.h" +#include "dev/gpio-hal.h" + +#include <stdint.h> +/*---------------------------------------------------------------------------*/ +#define CONFIG_MASK (IOC_IOPULL_M | IOC_INT_M | IOC_IOMODE_OPEN_SRC_INV) +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg) +{ + uint32_t config; + gpio_hal_pin_cfg_t tmp; + + /* Clear settings that we are about to change, keep everything else */ + config = ti_lib_rom_ioc_port_configure_get(pin); + config &= ~CONFIG_MASK; + + tmp = cfg & GPIO_HAL_PIN_CFG_EDGE_BOTH; + if(tmp == GPIO_HAL_PIN_CFG_EDGE_NONE) { + config |= IOC_NO_EDGE; + } else if(tmp == GPIO_HAL_PIN_CFG_EDGE_RISING) { + config |= IOC_RISING_EDGE; + } else if(tmp == GPIO_HAL_PIN_CFG_EDGE_FALLING) { + config |= IOC_FALLING_EDGE; + } else if(tmp == GPIO_HAL_PIN_CFG_EDGE_BOTH) { + config |= IOC_BOTH_EDGES; + } + + tmp = cfg & GPIO_HAL_PIN_CFG_PULL_MASK; + if(tmp == GPIO_HAL_PIN_CFG_PULL_NONE) { + config |= IOC_NO_IOPULL; + } else if(tmp == GPIO_HAL_PIN_CFG_PULL_DOWN) { + config |= IOC_IOPULL_DOWN; + } else if(tmp == GPIO_HAL_PIN_CFG_PULL_UP) { + config |= IOC_IOPULL_UP; + } + + tmp = cfg & GPIO_HAL_PIN_CFG_INT_MASK; + if(tmp == GPIO_HAL_PIN_CFG_INT_DISABLE) { + config |= IOC_INT_DISABLE; + } else if(tmp == GPIO_HAL_PIN_CFG_INT_ENABLE) { + config |= IOC_INT_ENABLE; + } + + ti_lib_rom_ioc_port_configure_set(pin, IOC_PORT_GPIO, config); +} +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_cfg_t +gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin) +{ + gpio_hal_pin_cfg_t cfg; + uint32_t tmp; + uint32_t config; + + cfg = 0; + config = ti_lib_rom_ioc_port_configure_get(pin); + + /* Pull */ + tmp = config & IOC_IOPULL_M; + if(tmp == IOC_IOPULL_UP) { + cfg |= GPIO_HAL_PIN_CFG_PULL_UP; + } else if(tmp == IOC_IOPULL_DOWN) { + cfg |= GPIO_HAL_PIN_CFG_PULL_DOWN; + } else if(tmp == IOC_NO_IOPULL) { + cfg |= GPIO_HAL_PIN_CFG_PULL_NONE; + } + + /* Interrupt enable/disable */ + tmp = config & IOC_INT_ENABLE; + if(tmp == IOC_INT_DISABLE) { + cfg |= GPIO_HAL_PIN_CFG_INT_DISABLE; + } else if(tmp == IOC_INT_ENABLE) { + cfg |= GPIO_HAL_PIN_CFG_INT_ENABLE; + } + + /* Edge detection */ + tmp = config & IOC_BOTH_EDGES; + if(tmp == IOC_NO_EDGE) { + cfg |= GPIO_HAL_PIN_CFG_EDGE_NONE; + } else if(tmp == IOC_FALLING_EDGE) { + cfg |= GPIO_HAL_PIN_CFG_EDGE_FALLING; + } else if(tmp == IOC_RISING_EDGE) { + cfg |= GPIO_HAL_PIN_CFG_EDGE_RISING; + } else if(tmp == IOC_BOTH_EDGES) { + cfg |= GPIO_HAL_PIN_CFG_EDGE_BOTH; + } + + return cfg; +} +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_mask_t +gpio_hal_arch_read_pins(gpio_hal_pin_mask_t pins) +{ + gpio_hal_pin_mask_t oe_pins; + + /* For pins configured as output we need to read DOUT31_0 */ + oe_pins = ti_lib_gpio_get_output_enable_multi_dio(pins); + + pins &= ~oe_pins; + + return (HWREG(GPIO_BASE + GPIO_O_DOUT31_0) & oe_pins) | + ti_lib_gpio_read_multi_dio(pins); +} +/*---------------------------------------------------------------------------*/ +uint8_t +gpio_hal_arch_read_pin(gpio_hal_pin_t pin) +{ + if(ti_lib_gpio_get_output_enable_dio(pin)) { + return (HWREG(GPIO_BASE + GPIO_O_DOUT31_0) >> pin) & 1; + } + + return ti_lib_gpio_read_dio(pin); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.h b/arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.h new file mode 100644 index 0000000000000000000000000000000000000000..7d87670c55cc764bcdf385055cc695bd80a9a96d --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc26xx + * @{ + * + * \defgroup cc26xx-gpio-hal CC13xx/CC26xx GPIO HAL implementation + * + * @{ + * + * \file + * Header file for the CC13xx/CC26xx GPIO HAL functions + * + * \note + * Do not include this header directly + */ +/*---------------------------------------------------------------------------*/ +#ifndef GPIO_HAL_ARCH_H_ +#define GPIO_HAL_ARCH_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "ti-lib.h" +#include "ti-lib-rom.h" + +#include <stdint.h> +/*---------------------------------------------------------------------------*/ +#define gpio_hal_arch_interrupt_enable(p) interrupt_enable(p) +#define gpio_hal_arch_interrupt_disable(p) ti_lib_rom_ioc_int_disable(p) + +#define gpio_hal_arch_pin_set_input(p) ti_lib_rom_ioc_pin_type_gpio_input(p) +#define gpio_hal_arch_pin_set_output(p) ti_lib_rom_ioc_pin_type_gpio_output(p) + +#define gpio_hal_arch_set_pin(p) ti_lib_gpio_set_dio(p) +#define gpio_hal_arch_clear_pin(p) ti_lib_gpio_clear_dio(p) +#define gpio_hal_arch_toggle_pin(p) ti_lib_gpio_toggle_dio(p) +#define gpio_hal_arch_write_pin(p, v) ti_lib_gpio_write_dio(p, v) + +#define gpio_hal_arch_set_pins(p) ti_lib_gpio_set_multi_dio(p) +#define gpio_hal_arch_clear_pins(p) ti_lib_gpio_clear_multi_dio(p) +#define gpio_hal_arch_toggle_pins(p) ti_lib_gpio_toggle_multi_dio(p) +#define gpio_hal_arch_write_pins(p, v) ti_lib_gpio_write_multi_dio(p, v) +/*---------------------------------------------------------------------------*/ +static inline void +interrupt_enable(gpio_hal_pin_t pin) +{ + ti_lib_gpio_clear_event_dio(pin); + ti_lib_rom_ioc_int_enable(pin); +} +/*---------------------------------------------------------------------------*/ +#endif /* GPIO_HAL_ARCH_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.c b/arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.c index 348d0646ab960abf920b783234317e0c3d236aab..c90e9239d760418ffe584f50581e756c1f39feb2 100644 --- a/arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.c +++ b/arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.c @@ -29,72 +29,33 @@ */ /*---------------------------------------------------------------------------*/ /** - * \addtogroup cc26xx-gpio-interrupts + * \addtogroup cc26xx * @{ * * \file - * Implementation of CC13xx/CC26xx GPIO interrupt handling. + * CC13xx/CC26xx GPIO interrupt ISR. */ /*---------------------------------------------------------------------------*/ -#include "ioc.h" -#include "gpio-interrupt.h" -#include "lpm.h" +#include "contiki.h" +#include "dev/gpio-hal.h" #include "ti-lib.h" #include <string.h> /*---------------------------------------------------------------------------*/ #define gpio_interrupt_isr GPIOIntHandler /*---------------------------------------------------------------------------*/ -/* Handler array */ -static gpio_interrupt_handler_t handlers[NUM_IO_MAX]; -/*---------------------------------------------------------------------------*/ -void -gpio_interrupt_register_handler(uint8_t ioid, gpio_interrupt_handler_t f) -{ - uint8_t interrupts_disabled = ti_lib_int_master_disable(); - - /* Clear interrupts on specified pins */ - ti_lib_gpio_clear_event_dio(ioid); - - handlers[ioid] = f; - - /* Re-enable interrupts */ - if(!interrupts_disabled) { - ti_lib_int_master_enable(); - } -} -/*---------------------------------------------------------------------------*/ -void -gpio_interrupt_init() -{ - int i; - - for(i = 0; i < NUM_IO_MAX; i++) { - handlers[i] = NULL; - } - - ti_lib_int_enable(INT_AON_GPIO_EDGE); -} -/*---------------------------------------------------------------------------*/ void gpio_interrupt_isr(void) { - uint32_t pin_mask; - uint8_t i; + gpio_hal_pin_mask_t pin_mask; /* Read interrupt flags */ pin_mask = (HWREG(GPIO_BASE + GPIO_O_EVFLAGS31_0) & GPIO_DIO_ALL_MASK); + gpio_hal_event_handler(pin_mask); + /* Clear the interrupt flags */ HWREG(GPIO_BASE + GPIO_O_EVFLAGS31_0) = pin_mask; - - /* Run custom ISRs */ - for(i = 0; i < NUM_IO_MAX; i++) { - /* Call the handler if there is one registered for this event */ - if((pin_mask & (1 << i)) && handlers[i] != NULL) { - handlers[i](i); - } - } } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/arch/cpu/cc26xx-cc13xx/dev/spi-arch.c b/arch/cpu/cc26xx-cc13xx/dev/spi-arch.c new file mode 100644 index 0000000000000000000000000000000000000000..d274a1d527a6eb8496087246b1e25b8240500df5 --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/dev/spi-arch.c @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2017, University of Bristol - http://www.bristol.ac.uk/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "contiki.h" +#include "ti-lib.h" +#include "dev/spi.h" +#include "sys/mutex.h" + +#include <stdint.h> +#include <stdbool.h> + +typedef struct spi_locks_s { + mutex_t lock; + spi_device_t *owner; +} spi_locks_t; + +/* One lock per SPI controller */ +spi_locks_t board_spi_locks_spi[SPI_CONTROLLER_COUNT] = { { MUTEX_STATUS_UNLOCKED, NULL } }; + +/*---------------------------------------------------------------------------*/ +/* Arch-specific properties of each SPI controller */ +typedef struct board_spi_controller_s { + uint32_t ssi_base; + uint32_t power_domain; + uint32_t prcm_periph; + uint32_t ssi_clkgr_clk_en; +} board_spi_controller_t; + +static const board_spi_controller_t spi_controller[SPI_CONTROLLER_COUNT] = { + { + .ssi_base = SSI0_BASE, + .power_domain = PRCM_DOMAIN_SERIAL, + .prcm_periph = PRCM_PERIPH_SSI0, + .ssi_clkgr_clk_en = PRCM_SSICLKGR_CLK_EN_SSI0 + }, + { + .ssi_base = SSI1_BASE, + .power_domain = PRCM_DOMAIN_PERIPH, + .prcm_periph = PRCM_PERIPH_SSI1, + .ssi_clkgr_clk_en = PRCM_SSICLKGR_CLK_EN_SSI1 + } +}; +/*---------------------------------------------------------------------------*/ +bool +spi_arch_has_lock(spi_device_t *dev) +{ + if(board_spi_locks_spi[dev->spi_controller].owner == dev) { + return true; + } + + return false; +} +/*---------------------------------------------------------------------------*/ +bool +spi_arch_is_bus_locked(spi_device_t *dev) +{ + if(board_spi_locks_spi[dev->spi_controller].lock == MUTEX_STATUS_LOCKED) { + return true; + } + + return false; +} +/*---------------------------------------------------------------------------*/ +static uint32_t +get_mode(spi_device_t *dev) +{ + /* Select the correct SPI mode */ + if(dev->spi_pha == 0 && dev->spi_pol == 0) { + return SSI_FRF_MOTO_MODE_0; + } else if(dev->spi_pha != 0 && dev->spi_pol == 0) { + return SSI_FRF_MOTO_MODE_1; + } else if(dev->spi_pha == 0 && dev->spi_pol != 0) { + return SSI_FRF_MOTO_MODE_2; + } else { + return SSI_FRF_MOTO_MODE_3; + } +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_arch_lock_and_open(spi_device_t *dev) +{ + uint32_t c; + + /* Lock the SPI bus */ + if(mutex_try_lock(&board_spi_locks_spi[dev->spi_controller].lock) == false) { + return SPI_DEV_STATUS_BUS_LOCKED; + } + + board_spi_locks_spi[dev->spi_controller].owner = dev; + + /* CS pin configuration */ + ti_lib_ioc_pin_type_gpio_output(dev->pin_spi_cs); + + /* First, make sure the SERIAL PD is on */ + ti_lib_prcm_power_domain_on(spi_controller[dev->spi_controller].power_domain); + while((ti_lib_prcm_power_domain_status(spi_controller[dev->spi_controller].power_domain) + != PRCM_DOMAIN_POWER_ON)) ; + + /* Enable clock in active mode */ + ti_lib_rom_prcm_peripheral_run_enable(spi_controller[dev->spi_controller].prcm_periph); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()) ; + + /* SPI configuration */ + ti_lib_ssi_int_disable(spi_controller[dev->spi_controller].ssi_base, SSI_RXOR | SSI_RXFF | SSI_RXTO | SSI_TXFF); + ti_lib_ssi_int_clear(spi_controller[dev->spi_controller].ssi_base, SSI_RXOR | SSI_RXTO); + ti_lib_rom_ssi_config_set_exp_clk(spi_controller[dev->spi_controller].ssi_base, ti_lib_sys_ctrl_clock_get(), + get_mode(dev), SSI_MODE_MASTER, dev->spi_bit_rate, 8); + ti_lib_rom_ioc_pin_type_ssi_master(spi_controller[dev->spi_controller].ssi_base, dev->pin_spi_miso, + dev->pin_spi_mosi, IOID_UNUSED, dev->pin_spi_sck); + + ti_lib_ssi_enable(spi_controller[dev->spi_controller].ssi_base); + + /* Get rid of residual data from SSI port */ + while(ti_lib_ssi_data_get_non_blocking(spi_controller[dev->spi_controller].ssi_base, &c)) ; + + return SPI_DEV_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_arch_close_and_unlock(spi_device_t *dev) +{ + if(!spi_arch_has_lock(dev)) { + return SPI_DEV_STATUS_BUS_NOT_OWNED; + } + + /* Power down SSI */ + ti_lib_rom_prcm_peripheral_run_disable(spi_controller[dev->spi_controller].prcm_periph); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()) ; + + /* Restore pins to a low-consumption state */ + ti_lib_ioc_pin_type_gpio_input(dev->pin_spi_miso); + ti_lib_ioc_io_port_pull_set(dev->pin_spi_miso, IOC_IOPULL_DOWN); + + ti_lib_ioc_pin_type_gpio_input(dev->pin_spi_mosi); + ti_lib_ioc_io_port_pull_set(dev->pin_spi_mosi, IOC_IOPULL_DOWN); + + ti_lib_ioc_pin_type_gpio_input(dev->pin_spi_sck); + ti_lib_ioc_io_port_pull_set(dev->pin_spi_sck, IOC_IOPULL_DOWN); + + /* Unlock the SPI bus */ + board_spi_locks_spi[dev->spi_controller].owner = NULL; + mutex_unlock(&board_spi_locks_spi[dev->spi_controller].lock); + + return SPI_DEV_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_arch_transfer(spi_device_t *dev, + const uint8_t *write_buf, int wlen, + uint8_t *inbuf, int rlen, int ignore_len) +{ + int i; + int totlen; + uint32_t c; + + if(!spi_arch_has_lock(dev)) { + return SPI_DEV_STATUS_BUS_NOT_OWNED; + } + + if(ti_lib_prcm_power_domain_status(spi_controller[dev->spi_controller].power_domain) + != PRCM_DOMAIN_POWER_ON) { + return SPI_DEV_STATUS_CLOSED; + } + + /* Then check the 'run mode' clock gate */ + if(!(HWREG(PRCM_BASE + PRCM_O_SSICLKGR) & spi_controller[dev->spi_controller].ssi_clkgr_clk_en)) { + return SPI_DEV_STATUS_CLOSED; + } + + totlen = MAX(rlen + ignore_len, wlen); + + if(totlen == 0) { + /* Nothing to do */ + return SPI_DEV_STATUS_OK; + } + + for(i = 0; i < totlen; i++) { + c = i < wlen ? write_buf[i] : 0; + ti_lib_ssi_data_put(spi_controller[dev->spi_controller].ssi_base, (uint8_t)c); + ti_lib_rom_ssi_data_get(spi_controller[dev->spi_controller].ssi_base, &c); + if(i < rlen) { + inbuf[i] = (uint8_t)c; + } + } + + while(ti_lib_rom_ssi_data_get_non_blocking(spi_controller[dev->spi_controller].ssi_base, &c)) ; + + return SPI_DEV_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_arch_select(spi_device_t *dev) +{ + + if(!spi_arch_has_lock(dev)) { + return SPI_DEV_STATUS_BUS_NOT_OWNED; + } + + ti_lib_gpio_clear_dio(dev->pin_spi_cs); + + return SPI_DEV_STATUS_OK; +} +spi_status_t +spi_arch_deselect(spi_device_t *dev) +{ + ti_lib_gpio_set_dio(dev->pin_spi_cs); + + return SPI_DEV_STATUS_OK; +} diff --git a/arch/cpu/cc26xx-cc13xx/doxygen-group.txt b/arch/cpu/cc26xx-cc13xx/doxygen-group.txt new file mode 100644 index 0000000000000000000000000000000000000000..6dd3cd1f0b733a3d82d004737e23315a78d4df61 --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/doxygen-group.txt @@ -0,0 +1,16 @@ +/** + * \defgroup cc26xx The TI CC13xx and CC26xx Systems-on-Chip + * + * This group documents the TI CC26xx and CC13xx CPUs. The two CPU families are + * very similar, with the main difference being related to radio capability. + * + * Documentation in this group should be considered to be applicable to both + * families, unless explicitly stated otherwise. + * + * \ingroup cpu + */ + +/** + * \defgroup cc26xx-platforms TI CC26xx-powered platforms + * \ingroup platform + */ diff --git a/arch/cpu/cc26xx-cc13xx/int-master.c b/arch/cpu/cc26xx-cc13xx/int-master.c new file mode 100644 index 0000000000000000000000000000000000000000..e6b513d634aaf5e627a43d11704c95c4ee0867c6 --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/int-master.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc26xx + * @{ + * + * \defgroup cc26xx-interrupts CC13xx-CC26xx master interrupt manipulation + * + * Master interrupt manipulation routines for the CC13xx and CC26xx CPUs + * + * @{ + * + * \file + * Master interrupt manipulation implementation for the TI CC13xx/CC26xx + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "sys/int-master.h" +#include "cc13x0-cc26x0-cm3.h" + +#include "ti-lib.h" + +#include <stdbool.h> +/*---------------------------------------------------------------------------*/ +void +int_master_enable(void) +{ + ti_lib_int_master_enable(); +} +/*---------------------------------------------------------------------------*/ +int_master_status_t +int_master_read_and_disable(void) +{ + return ti_lib_int_master_disable(); +} +/*---------------------------------------------------------------------------*/ +void +int_master_status_set(int_master_status_t status) +{ + __set_PRIMASK(status); +} +/*---------------------------------------------------------------------------*/ +bool +int_master_is_enabled(void) +{ + return ti_lib_cpu_primask() ? false : true; +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/arch/cpu/cc26xx-cc13xx/lib/cc13xxware b/arch/cpu/cc26xx-cc13xx/lib/cc13xxware index f4800b7af65e78fd45e0a1f72648abf70a9fe567..682cf5d60aa6b6be77c5519ff70fa18087fe3cf0 160000 --- a/arch/cpu/cc26xx-cc13xx/lib/cc13xxware +++ b/arch/cpu/cc26xx-cc13xx/lib/cc13xxware @@ -1 +1 @@ -Subproject commit f4800b7af65e78fd45e0a1f72648abf70a9fe567 +Subproject commit 682cf5d60aa6b6be77c5519ff70fa18087fe3cf0 diff --git a/arch/cpu/cc26xx-cc13xx/lib/cc26xxware b/arch/cpu/cc26xx-cc13xx/lib/cc26xxware index 40916ad11efdcac76775b9b18cebc8d0c37c48f2..568511d650601afdc80106d9b9d5c44882635d17 160000 --- a/arch/cpu/cc26xx-cc13xx/lib/cc26xxware +++ b/arch/cpu/cc26xx-cc13xx/lib/cc26xxware @@ -1 +1 @@ -Subproject commit 40916ad11efdcac76775b9b18cebc8d0c37c48f2 +Subproject commit 568511d650601afdc80106d9b9d5c44882635d17 diff --git a/arch/cpu/cc26xx-cc13xx/lpm.c b/arch/cpu/cc26xx-cc13xx/lpm.c index 48ded636e43226e361ef3b039bf689a217055385..a5e746f24b0be9f356babccd13c52b6caf95df27 100644 --- a/arch/cpu/cc26xx-cc13xx/lpm.c +++ b/arch/cpu/cc26xx-cc13xx/lpm.c @@ -185,7 +185,7 @@ wake_up(void) { lpm_registered_module_t *module; - ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU); + ENERGEST_SWITCH(ENERGEST_TYPE_DEEP_LPM, ENERGEST_TYPE_CPU); /* Sync so that we get the latest values before adjusting recharge settings */ ti_lib_sys_ctrl_aon_sync(); @@ -485,7 +485,7 @@ deep_sleep(void) ti_lib_pwr_ctrl_source_set(PWRCTRL_PWRSRC_ULDO); } - ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM); + ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_DEEP_LPM); /* Sync the AON interface to ensure all writes have gone through. */ ti_lib_sys_ctrl_aon_sync(); diff --git a/arch/cpu/cc26xx-cc13xx/mtarch.h b/arch/cpu/cc26xx-cc13xx/mtarch.h deleted file mode 100644 index 4f696669d5c858c64dc747ed49a9ee8b54e6ed02..0000000000000000000000000000000000000000 --- a/arch/cpu/cc26xx-cc13xx/mtarch.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2010, Loughborough University - Computer Science - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/* - * \file - * Stub header file for multi-threading. It doesn't do anything, it - * just exists so that mt.c can compile cleanly. - * - * This is based on the original mtarch.h for z80 by Takahide Matsutsuka - * - * \author - * George Oikonomou - <oikonomou@users.sourceforge.net> - */ -#ifndef __MTARCH_H__ -#define __MTARCH_H__ - -struct mtarch_thread { - unsigned char *sp; -}; - -#endif /* __MTARCH_H__ */ diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/ble-cc2650.c b/arch/cpu/cc26xx-cc13xx/rf-core/ble-cc2650.c new file mode 100644 index 0000000000000000000000000000000000000000..6510ac50e90e2f1976eeb9a0e4c266c1f1496b10 --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/rf-core/ble-cc2650.c @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2017, Graz University of Technology + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * BLE radio for the TI CC26xx platform + * + * \author + * Michael Spoerk <michael.spoerk@tugraz.at> + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/radio.h" +#include "os/dev/ble-hal.h" +#include "rf-core/ble-hal/ble-hal-cc26xx.h" + +#include <stdint.h> +#include <string.h> +/*---------------------------------------------------------------------------*/ +#include "sys/log.h" +#define LOG_MODULE "RADIO" +#define LOG_LEVEL LOG_LEVEL_MAIN +/*---------------------------------------------------------------------------*/ +static uint16_t adv_interval; +static ble_adv_type_t adv_type; +static ble_addr_type_t adv_own_addr_type; +static uint8_t adv_channel_map; +static uint16_t buffer_size = 0; +/*---------------------------------------------------------------------------*/ +static uint16_t scan_interval; +static uint16_t scan_window; +static ble_scan_type_t scan_type; +static ble_addr_type_t scan_own_addr_type; +/*---------------------------------------------------------------------------*/ +static ble_addr_type_t initiator_peer_addr_type; +static uint8_t initiator_peer_addr[BLE_ADDR_SIZE]; +/*---------------------------------------------------------------------------*/ +static uint16_t connection_interval; +static uint16_t connection_latency; +static uint16_t connection_timeout; +/*---------------------------------------------------------------------------*/ +static int +init(void) +{ + int result = ble_hal.reset(); + return result == BLE_RESULT_OK; +} +/*---------------------------------------------------------------------------*/ +static int +send(const void *payload, unsigned short payload_len) +{ + uint8_t res; + res = ble_hal.send((void *)payload, payload_len); + LOG_DBG("ble-mode send() %d bytes\n", payload_len); + if(res == BLE_RESULT_OK) { + return RADIO_TX_OK; + } else { + LOG_ERR("ble-mode send() error: %d\n", res); + return RADIO_TX_ERR; + } +} +/*---------------------------------------------------------------------------*/ +static int +on(void) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +off(void) +{ + ble_hal.disconnect(0, 0); + return 1; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_value(radio_param_t param, radio_value_t *value) +{ + unsigned int temp; + + if(!value) { + return RADIO_RESULT_INVALID_VALUE; + } + + switch(param) { + case RADIO_CONST_CHANNEL_MIN: + *value = BLE_DATA_CHANNEL_MIN; + return RADIO_RESULT_OK; + case RADIO_CONST_CHANNEL_MAX: + *value = BLE_DATA_CHANNEL_MAX; + return RADIO_RESULT_OK; + case RADIO_CONST_BLE_BUFFER_SIZE: + if(buffer_size == 0) { + ble_hal.read_buffer_size((unsigned int *)&buffer_size, &temp); + } + memcpy(value, &buffer_size, 2); + return RADIO_RESULT_OK; + case RADIO_CONST_BLE_BUFFER_AMOUNT: + ble_hal.read_buffer_size(&temp, (unsigned int *)value); + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_CONN_INTERVAL: + ble_hal.read_connection_interval(0, (unsigned int *)value); + return RADIO_RESULT_OK; + default: + return RADIO_RESULT_NOT_SUPPORTED; + } +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_value(radio_param_t param, radio_value_t value) +{ + switch(param) { + case RADIO_PARAM_BLE_ADV_INTERVAL: + if((value > BLE_ADV_INTERVAL_MAX) || (value < BLE_ADV_INTERVAL_MIN)) { + return RADIO_RESULT_INVALID_VALUE; + } + adv_interval = (uint16_t)value; + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_ADV_TYPE: + adv_type = value; + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_ADV_OWN_ADDR_TYPE: + adv_own_addr_type = value; + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_ADV_CHANNEL_MAP: + adv_channel_map = value; + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_ADV_ENABLE: + if(value) { + /* set the advertisement parameter before enabling */ + ble_hal.set_adv_param(adv_interval, adv_type, + adv_own_addr_type, adv_channel_map); + } + ble_hal.set_adv_enable(value); + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_SCAN_INTERVAL: + if((value > BLE_SCAN_INTERVAL_MAX) || (value < BLE_SCAN_INTERVAL_MIN)) { + return RADIO_RESULT_INVALID_VALUE; + } + scan_interval = (uint16_t)value; + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_SCAN_WINDOW: + if((value > BLE_SCAN_INTERVAL_MAX) || (value < BLE_SCAN_INTERVAL_MIN)) { + return RADIO_RESULT_INVALID_VALUE; + } + scan_window = (uint16_t)value; + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_SCAN_TYPE: + scan_type = value; + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_SCAN_OWN_ADDR_TYPE: + scan_own_addr_type = value; + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_SCAN_ENABLE: + if(value) { + ble_hal.set_scan_param(scan_type, scan_interval, + scan_window, scan_own_addr_type); + } + ble_hal.set_scan_enable(value, 0); + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_PEER_ADDR_TYPE: + initiator_peer_addr_type = value; + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_CONN_INTERVAL: + connection_interval = value; + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_CONN_LATENCY: + connection_latency = value; + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_CONN_SUPERVISION_TIMEOUT: + connection_timeout = value; + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_INITIATOR_ENABLE: + if(value) { + ble_hal.create_connection(scan_interval, scan_window, + initiator_peer_addr_type, + initiator_peer_addr, + scan_own_addr_type, + connection_interval, + connection_latency, + connection_timeout); + } else { + ble_hal.create_connection_cancel(); + } + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_CONN_UPDATE: + if(value) { + return ble_hal.connection_update(0, connection_interval, connection_latency, connection_timeout); + } else { + return RADIO_RESULT_INVALID_VALUE; + } + default: + return RADIO_RESULT_NOT_SUPPORTED; + } +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + switch(param) { + case RADIO_CONST_BLE_BD_ADDR: + if(size != BLE_ADDR_SIZE || !dest) { + return RADIO_RESULT_INVALID_VALUE; + } + ble_hal.read_bd_addr(dest); + return RADIO_RESULT_OK; + } + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_object(radio_param_t param, const void *src, size_t size) +{ + switch(param) { + case RADIO_PARAM_BLE_ADV_PAYLOAD: + if(size <= 0 || size >= BLE_ADV_DATA_LEN || !src) { + return RADIO_RESULT_INVALID_VALUE; + } + ble_hal.set_adv_data((unsigned short)size, (char *)src); + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_ADV_SCAN_RESPONSE: + if(size <= 0 || size >= BLE_SCAN_RESP_DATA_LEN || !src) { + return RADIO_RESULT_INVALID_VALUE; + } + ble_hal.set_scan_resp_data((unsigned short)size, (char *)src); + return RADIO_RESULT_OK; + case RADIO_PARAM_BLE_PEER_ADDR: + if(size <= 0 || size > BLE_ADDR_SIZE || !src) { + return RADIO_RESULT_INVALID_VALUE; + } + memcpy(initiator_peer_addr, src, size); + return RADIO_RESULT_OK; + } + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +const struct radio_driver ble_cc2650_driver = { + init, + NULL, + NULL, + send, + NULL, + NULL, + NULL, + NULL, + on, + off, + get_value, + set_value, + get_object, + set_object, +}; +/*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/ble-hal-cc26xx.c b/arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/ble-hal-cc26xx.c new file mode 100644 index 0000000000000000000000000000000000000000..d4c761dcdde5eda54934295f8681e831536d7997 --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/ble-hal-cc26xx.c @@ -0,0 +1,1017 @@ +/* + * Copyright (c) 2017, Graz University of Technology + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * BLE radio hardware abstraction implementation for the TI CC26XX controller + * + * \author + * Michael Spoerk <michael.spoerk@tugraz.at> + */ +/*---------------------------------------------------------------------------*/ + +#include "lpm.h" + +#include "sys/rtimer.h" +#include "sys/process.h" + +#include "os/dev/ble-hal.h" +#include "dev/oscillators.h" + +#include "ble-addr.h" + +#include "net/netstack.h" +#include "net/packetbuf.h" + +#include "rf_data_entry.h" +#include "rf-core/rf-core.h" +#include "rf_ble_cmd.h" +#include "lib/random.h" + +#include "ioc.h" +#include "ti-lib.h" +#include "inc/hw_types.h" +#include "inc/hw_rfc_dbell.h" + +#include <string.h> + +#include "rf-core/ble-hal/rf-ble-cmd.h" +/*---------------------------------------------------------------------------*/ +#include "sys/log.h" +#define LOG_MODULE "BLE-RADIO" +#define LOG_LEVEL LOG_LEVEL_MAIN +/*---------------------------------------------------------------------------*/ +#define CMD_GET_STATUS(X) (((rfc_radioOp_t *)X)->status) +#define RX_ENTRY_STATUS(X) (((rfc_dataEntry_t *)X)->status) +#define RX_ENTRY_LENGTH(X) (((rfc_dataEntry_t *)X)->length) +#define RX_ENTRY_TYPE(X) (((rfc_dataEntry_t *)X)->config.type) +#define RX_ENTRY_NEXT_ENTRY(X) (((rfc_dataEntry_t *)X)->pNextEntry) +#define RX_ENTRY_DATA_LENGTH(X) ((X)[8]) +#define RX_ENTRY_DATA_PTR(X) (&(X)[9]) +#define TX_ENTRY_STATUS(X) RX_ENTRY_STATUS(X) +#define TX_ENTRY_LENGTH(X) RX_ENTRY_LENGTH(X) +#define TX_ENTRY_TYPE(X) RX_ENTRY_TYPE(X) +#define TX_ENTRY_NEXT_ENTRY(X) RX_ENTRY_NEXT_ENTRY(X) +#define TX_ENTRY_FRAME_TYPE(X) ((X)[8]) +#define TX_ENTRY_DATA_PTR(X) (&(X)[9]) +/*---------------------------------------------------------------------------*/ +/* LPM */ +/*---------------------------------------------------------------------------*/ +static uint8_t +request(void) +{ + if(rf_core_is_accessible()) { + return LPM_MODE_SLEEP; + } + + return LPM_MODE_MAX_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +LPM_MODULE(cc26xx_ble_lpm_module, request, NULL, NULL, LPM_DOMAIN_NONE); +/*---------------------------------------------------------------------------*/ +/* timing utilities */ +#define TIME_UNIT_MS 1000 /* 1000 times per second */ +#define TIME_UNIT_0_625_MS 1600 /* 1600 times per second */ +#define TIME_UNIT_1_25_MS 800 /* 800 times per second */ +#define TIME_UNIT_10_MS 100 /* 100 times per second */ +#define TIME_UNIT_RF_CORE 4000000 /* runs at 4 MHz */ +#define TIME_UNIT_RTIMER RTIMER_SECOND + +rtimer_clock_t +ticks_from_unit(uint32_t value, uint32_t unit) +{ + double temp = (((double)value) / unit) * RTIMER_SECOND; + return (rtimer_clock_t)temp; +} +uint32_t +ticks_to_unit(rtimer_clock_t value, uint32_t unit) +{ + double temp = (((double)value) / RTIMER_SECOND) * unit; + return (uint32_t)temp; +} +/*---------------------------------------------------------------------------*/ +#define CMD_BUFFER_SIZE 24 +#define PARAM_BUFFER_SIZE 36 +#define OUTPUT_BUFFER_SIZE 24 +/*---------------------------------------------------------------------------*/ +/* ADVERTISING data structures */ +#define ADV_RX_BUFFERS_OVERHEAD 8 +#define ADV_RX_BUFFERS_DATA_LEN 60 +#define ADV_RX_BUFFERS_LEN (ADV_RX_BUFFERS_OVERHEAD + ADV_RX_BUFFERS_DATA_LEN) +#define ADV_RX_BUFFERS_NUM 2 + +#define ADV_PREPROCESSING_TIME_TICKS 65 + +typedef struct { + /* PARAMETER */ + uint16_t adv_interval; + ble_adv_type_t adv_type; + ble_addr_type_t own_addr_type; + uint8_t channel_map; + uint8_t adv_data_len; + uint8_t adv_data[BLE_ADV_DATA_LEN]; + uint8_t scan_rsp_data_len; + uint8_t scan_rsp_data[BLE_ADV_DATA_LEN]; + /* STATE information */ + uint8_t active; + rtimer_clock_t start_rt; + struct rtimer timer; + /* utility */ + uint8_t cmd_buf[CMD_BUFFER_SIZE]; + uint8_t param_buf[PARAM_BUFFER_SIZE]; + uint8_t output_buf[OUTPUT_BUFFER_SIZE]; + dataQueue_t rx_queue; + uint8_t rx_buffers[ADV_RX_BUFFERS_NUM][ADV_RX_BUFFERS_LEN]; + uint8_t *rx_queue_current; +} ble_adv_param_t; + +static ble_adv_param_t adv_param; +static void advertising_event(struct rtimer *t, void *ptr); +/*---------------------------------------------------------------------------*/ +/* CONNECTION data structures */ +#define BLE_MODE_MAX_CONNECTIONS 1 + +/* maximum packet length that is transmitted during a single connection event*/ +#ifdef BLE_MODE_CONF_CONN_MAX_PACKET_SIZE +#define BLE_MODE_CONN_MAX_PACKET_SIZE BLE_MODE_CONF_CONN_MAX_PACKET_SIZE +#else +#define BLE_MODE_CONN_MAX_PACKET_SIZE 256 +#endif + +#define CONN_BLE_BUFFER_SIZE 27 /* maximum size of the data buffer */ + +#define CONN_RX_BUFFERS_OVERHEAD 8 +#define CONN_RX_BUFFERS_DATA_LEN 60 +#define CONN_RX_BUFFERS_LEN (CONN_RX_BUFFERS_OVERHEAD + CONN_RX_BUFFERS_DATA_LEN) +#define CONN_RX_BUFFERS_NUM 12 + +/* custom status used for tx buffers */ +#define DATA_ENTRY_FREE 5 +#define DATA_ENTRY_QUEUED 6 + +#define CONN_TX_BUFFERS_OVERHEAD 9 +#define CONN_TX_BUFFERS_DATA_LEN 27 +#define CONN_TX_BUFFERS_LEN (CONN_TX_BUFFERS_OVERHEAD + CONN_TX_BUFFERS_DATA_LEN) +#define CONN_TX_BUFFERS_NUM 12 + +#define CONN_WIN_SIZE 1 +#define CONN_WIN_OFFSET 20 + +#define CONN_EVENT_LATENCY_THRESHOLD 10 +#define CONN_WINDOW_WIDENING_TICKS 30 /* appr. 0.46 ms */ +#define CONN_PREPROCESSING_TIME_TICKS 100 /* 1.5 ms */ + +#define CONN_UPDATE_DELAY 6 + +typedef struct { + /* PARAMETER */ + uint8_t peer_address[BLE_ADDR_SIZE]; + uint32_t access_address; + uint8_t crc_init_0; + uint8_t crc_init_1; + uint8_t crc_init_2; + uint8_t win_size; + uint16_t win_offset; + uint16_t interval; + uint16_t latency; + uint16_t timeout; + uint64_t channel_map; + uint8_t num_used_channels; + uint8_t hop; + uint8_t sca; + rtimer_clock_t timestamp_rt; + /* STATE information */ + uint8_t active; + uint16_t counter; + uint8_t unmapped_channel; + uint8_t mapped_channel; + rtimer_clock_t start_rt; + uint16_t conn_handle; + struct rtimer timer; + /* utility */ + uint8_t cmd_buf[CMD_BUFFER_SIZE]; + uint8_t param_buf[PARAM_BUFFER_SIZE]; + uint8_t output_buf[OUTPUT_BUFFER_SIZE]; + dataQueue_t rx_queue; + uint8_t rx_buffers[CONN_RX_BUFFERS_NUM][CONN_RX_BUFFERS_LEN]; + uint8_t *rx_queue_current; + dataQueue_t tx_queue; + uint8_t tx_buffers[CONN_TX_BUFFERS_NUM][CONN_TX_BUFFERS_LEN]; + uint8_t tx_buffers_sent; + uint16_t skipped_events; + /* channel map update */ + uint64_t channel_update_channel_map; + uint16_t channel_update_counter; + uint8_t channel_update_num_used_channels; + /* connection parameter update */ + uint8_t conn_update_win_size; + uint16_t conn_update_win_offset; + uint16_t conn_update_interval; + uint16_t conn_update_latency; + uint16_t conn_update_timeout; + uint16_t conn_update_counter; +} ble_conn_param_t; + +static ble_conn_param_t conn_param[BLE_MODE_MAX_CONNECTIONS]; + +static uint16_t conn_counter = 0; + +static void connection_event_slave(struct rtimer *t, void *ptr); +/*---------------------------------------------------------------------------*/ +PROCESS(ble_hal_conn_rx_process, "BLE/CC26xx connection RX process"); +process_event_t rx_data_event; +/*---------------------------------------------------------------------------*/ +static void +setup_buffers(void) +{ + uint8_t conn_count; + ble_conn_param_t *conn; + uint8_t i; + rfc_dataEntry_t *entry; + + /* setup advertisement RX buffer (circular buffer) */ + memset(&adv_param, 0x00, sizeof(ble_adv_param_t)); + memset(&adv_param.rx_queue, 0x00, sizeof(adv_param.rx_queue)); + adv_param.rx_queue.pCurrEntry = adv_param.rx_buffers[0]; + adv_param.rx_queue.pLastEntry = NULL; + adv_param.rx_queue_current = adv_param.rx_buffers[0]; + for(i = 0; i < ADV_RX_BUFFERS_NUM; i++) { + memset(&adv_param.rx_buffers[i], 0x00, ADV_RX_BUFFERS_LEN); + entry = (rfc_dataEntry_t *)adv_param.rx_buffers[i]; + entry->pNextEntry = adv_param.rx_buffers[(i + 1) % ADV_RX_BUFFERS_NUM]; + entry->config.lenSz = 1; + entry->length = ADV_RX_BUFFERS_DATA_LEN; + } + + memset(conn_param, 0x00, sizeof(ble_conn_param_t) * BLE_MODE_MAX_CONNECTIONS); + for(conn_count = 0; conn_count < BLE_MODE_MAX_CONNECTIONS; conn_count++) { + /* setup connection RX buffer (circular buffer) */ + conn = &conn_param[conn_count]; + memset(&conn->rx_queue, 0x00, sizeof(conn->rx_queue)); + conn->rx_queue.pCurrEntry = conn->rx_buffers[0]; + conn->rx_queue.pLastEntry = NULL; + conn->rx_queue_current = conn->rx_buffers[0]; + + for(i = 0; i < CONN_RX_BUFFERS_NUM; i++) { + memset(&conn->rx_buffers[i], 0x00, CONN_RX_BUFFERS_LEN); + entry = (rfc_dataEntry_t *)conn->rx_buffers[i]; + entry->pNextEntry = conn->rx_buffers[(i + 1) % CONN_RX_BUFFERS_NUM]; + entry->config.lenSz = 1; + entry->length = CONN_RX_BUFFERS_DATA_LEN; + } + + /* setup connection TX buffer (buffers are added on demand to the queue) */ + memset(&conn->tx_queue, 0x00, sizeof(conn->tx_queue)); + conn->tx_queue.pCurrEntry = NULL; + conn->tx_queue.pLastEntry = NULL; + + for(i = 0; i < CONN_TX_BUFFERS_NUM; i++) { + memset(&conn->tx_buffers[i], 0x00, CONN_TX_BUFFERS_LEN); + entry = (rfc_dataEntry_t *)conn->tx_buffers[i]; + entry->config.lenSz = 1; + entry->status = DATA_ENTRY_FREE; + } + } +} +/*---------------------------------------------------------------------------*/ +static ble_conn_param_t * +get_connection_for_handle(uint8_t conn_handle) +{ + uint8_t i; + for(i = 0; i < BLE_MODE_MAX_CONNECTIONS; i++) { + if(conn_param[i].conn_handle == conn_handle) { + return &conn_param[i]; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +static uint8_t * +tx_queue_get_buffer(ble_conn_param_t *param) +{ + uint8_t i; + rfc_dataEntry_t *entry; + for(i = 0; i < CONN_TX_BUFFERS_NUM; i++) { + entry = (rfc_dataEntry_t *)param->tx_buffers[i]; + if(entry->status == DATA_ENTRY_FREE) { + return (uint8_t *)entry; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +static uint16_t +tx_queue_count_free_buffers(ble_conn_param_t *param) +{ + uint16_t i; + uint16_t free_bufs = 0; + for(i = 0; i < CONN_TX_BUFFERS_NUM; i++) { + if(TX_ENTRY_STATUS(param->tx_buffers[i]) == DATA_ENTRY_FREE) { + free_bufs++; + } + } + return free_bufs; +} +/*---------------------------------------------------------------------------*/ +static uint8_t +tx_queue_data_to_transmit(ble_conn_param_t *param) +{ + uint16_t i; + for(i = 0; i < CONN_TX_BUFFERS_NUM; i++) { + if(TX_ENTRY_STATUS(param->tx_buffers[i]) == DATA_ENTRY_QUEUED) { + return 1; + } + } + return 0; +} +/*---------------------------------------------------------------------------*/ +ble_result_t +on(void) +{ + oscillators_request_hf_xosc(); + if(!rf_core_is_accessible()) { + /* boot the rf core */ + if(rf_core_boot() != RF_CORE_CMD_OK) { + LOG_ERR("ble_controller_reset() could not boot rf-core\n"); + return BLE_RESULT_ERROR; + } + + rf_core_setup_interrupts(0); + oscillators_switch_to_hf_xosc(); + + if(rf_ble_cmd_setup_ble_mode() != RF_BLE_CMD_OK) { + LOG_ERR("could not setup rf-core to BLE mode\n"); + return BLE_RESULT_ERROR; + } + } + return BLE_RESULT_OK; +} +/*---------------------------------------------------------------------------*/ +void +off(void) +{ + rf_core_power_down(); + oscillators_switch_to_hf_rc(); +} +/*---------------------------------------------------------------------------*/ +static ble_result_t +reset(void) +{ + LOG_INFO("maximum connections: %4d\n", BLE_MODE_MAX_CONNECTIONS); + LOG_INFO("max. packet length: %4d\n", BLE_MODE_CONN_MAX_PACKET_SIZE); + lpm_register_module(&cc26xx_ble_lpm_module); + rf_core_set_modesel(); + setup_buffers(); + if(on() != BLE_RESULT_OK) { + return BLE_RESULT_ERROR; + } + off(); + if(!process_is_running(&ble_hal_conn_rx_process)) { + rx_data_event = process_alloc_event(); + process_start(&ble_hal_conn_rx_process, NULL); + } + return BLE_RESULT_OK; +} +/*---------------------------------------------------------------------------*/ +static ble_result_t +read_bd_addr(uint8_t *addr) +{ + ble_addr_cpy_to(addr); + return BLE_RESULT_OK; +} +/*---------------------------------------------------------------------------*/ +static ble_result_t +read_buffer_size(unsigned int *buf_len, unsigned int *num_buf) +{ + uint16_t i; + uint16_t ll_buffers = CONN_TX_BUFFERS_NUM; + uint16_t packet_buffers; + uint16_t buffer_size; + for(i = 0; i < conn_counter; i++) { + ll_buffers = MIN(ll_buffers, tx_queue_count_free_buffers(&conn_param[i])); + } + packet_buffers = ll_buffers / (BLE_MODE_CONN_MAX_PACKET_SIZE / CONN_BLE_BUFFER_SIZE); + buffer_size = BLE_MODE_CONN_MAX_PACKET_SIZE; + memcpy(buf_len, &buffer_size, 2); + memcpy(num_buf, &packet_buffers, 2); + return BLE_RESULT_OK; +} +/*---------------------------------------------------------------------------*/ +static ble_result_t +set_adv_param(unsigned int adv_int, ble_adv_type_t type, + ble_addr_type_t own_type, unsigned short adv_map) +{ + adv_param.adv_interval = adv_int; + adv_param.adv_type = type; + adv_param.own_addr_type = own_type; + adv_param.channel_map = adv_map; + + LOG_INFO("advertising parameter: interval: %4d, channels: %2d\n", + adv_param.adv_interval, adv_param.channel_map); + + LOG_DBG("interval: %16u (ms)\n", adv_param.adv_interval); + LOG_DBG("type: %16u\n", adv_param.adv_type); + LOG_DBG("addr_type:%16u\n", adv_param.own_addr_type); + LOG_DBG("channels: %16u\n", adv_param.channel_map); + + return BLE_RESULT_OK; +} +/*---------------------------------------------------------------------------*/ +static ble_result_t +read_adv_channel_tx_power(short *power) +{ + return BLE_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static ble_result_t +set_adv_data(unsigned short data_len, char *data) +{ + if(data_len > BLE_ADV_DATA_LEN) { + LOG_WARN("BLE-HAL: adv_data too long\n"); + return BLE_RESULT_INVALID_PARAM; + } + adv_param.adv_data_len = data_len; + memcpy(adv_param.adv_data, data, data_len); + return BLE_RESULT_OK; +} +/*---------------------------------------------------------------------------*/ +static ble_result_t +set_scan_resp_data(unsigned short data_len, char *data) +{ + if(data_len > BLE_SCAN_RESP_DATA_LEN) { + LOG_WARN("BLE-HAL: scan_resp_data too long\n"); + return BLE_RESULT_INVALID_PARAM; + } + adv_param.scan_rsp_data_len = data_len; + memcpy(adv_param.scan_rsp_data, data, data_len); + return BLE_RESULT_OK; +} +/*---------------------------------------------------------------------------*/ +static ble_result_t +set_adv_enable(unsigned short enable) +{ + uint32_t now = RTIMER_NOW(); + if((enable) && (!adv_param.active)) { + adv_param.start_rt = now + ticks_from_unit(adv_param.adv_interval, + TIME_UNIT_1_25_MS); + rtimer_set(&adv_param.timer, adv_param.start_rt, + 0, advertising_event, (void *)&adv_param); + } + return BLE_RESULT_OK; +} +/*---------------------------------------------------------------------------*/ +static ble_result_t +send_frame(ble_conn_param_t *conn, uint8_t *data, uint8_t data_len, uint8_t frame_type) +{ + uint8_t *tx_buffer = tx_queue_get_buffer(conn); + if(tx_buffer == NULL) { + LOG_WARN("BLE-HAL: send_frame: no TX buffer available (conn_handle: 0x%04X)\n", conn->conn_handle); + return BLE_RESULT_ERROR; + } + if(data_len > CONN_BLE_BUFFER_SIZE) { + LOG_WARN("BLE-HAL: send_frame: data too long (%d bytes)\n", data_len); + return BLE_RESULT_ERROR; + } + + memcpy(TX_ENTRY_DATA_PTR(tx_buffer), data, data_len); + TX_ENTRY_LENGTH(tx_buffer) = data_len + 1; + TX_ENTRY_STATUS(tx_buffer) = DATA_ENTRY_QUEUED; + TX_ENTRY_FRAME_TYPE(tx_buffer) = frame_type; + return BLE_RESULT_OK; +} +/*---------------------------------------------------------------------------*/ +static ble_result_t +connection_update(unsigned int connection_handle, unsigned int conn_interval, + unsigned int conn_latency, unsigned int supervision_timeout) +{ + uint8_t len = 0; + uint8_t data[24]; + ble_conn_param_t *conn = get_connection_for_handle(connection_handle); + + if(conn == NULL) { + return BLE_RESULT_ERROR; + } + + LOG_INFO("connection_update: handle: 0x%04X, interval: %4d, latency: %2d, timeout: %4d\n", + connection_handle, conn_interval, conn_latency, supervision_timeout); +#if UIP_CONF_ROUTER + uint16_t instant = conn->counter + CONN_UPDATE_DELAY; + /* prepare connection update packet */ + data[0] = BLE_LL_CONN_UPDATE_REQ; + data[1] = conn->win_size; + data[2] = 0; + data[3] = 0; + memcpy(&data[4], &conn_interval, 2); + memcpy(&data[6], &conn_latency, 2); + memcpy(&data[8], &supervision_timeout, 2); + memcpy(&data[10], &instant, 2); + len = 12; + /* set new connection */ + conn->conn_update_win_size = conn->win_size; + conn->conn_update_interval = conn_interval; + conn->conn_update_latency = conn_latency; + conn->conn_update_timeout = supervision_timeout; + conn->conn_update_counter = instant; + + if(send_frame(conn, data, len, BLE_DATA_PDU_LLID_CONTROL) != BLE_RESULT_OK) { + LOG_ERR("connection_update: send frame was NOT successful\n"); + return BLE_RESULT_ERROR; + } +#else + data[0] = BLE_LL_CONN_PARAM_REQ; + memcpy(&data[1], &conn_interval, 2); /* interval min */ + memcpy(&data[3], &conn_interval, 2); /* interval max */ + memcpy(&data[5], &conn_latency, 2); /* latency */ + memcpy(&data[7], &supervision_timeout, 2); /* supervision timeout */ + memcpy(&data[9], &conn_interval, 1); /* preferred periodicity */ + memcpy(&data[10], &conn->counter, 2); /* referenc conn event count */ + memset(&data[12], 0xFF, 12); /* offset 0 to 5 */ + len = 24; + + if(send_frame(conn, data, len, BLE_DATA_PDU_LLID_CONTROL) != BLE_RESULT_OK) { + LOG_ERR("connection_update: send frame was NOT successful\n"); + return BLE_RESULT_ERROR; + } +#endif + return BLE_RESULT_OK; +} +/*---------------------------------------------------------------------------*/ +static ble_result_t +send(void *buf, unsigned short buf_len) +{ + uint16_t loop_data; + uint16_t loop_conn; + ble_conn_param_t *conn; + uint8_t *data; + uint16_t data_len; + linkaddr_t dest_addr; + linkaddr_t conn_addr; + uint8_t result; + + linkaddr_copy(&dest_addr, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); + + LOG_DBG("ble-hal: sending %d bytes\n", buf_len); + + for(loop_conn = 0; loop_conn < conn_counter; loop_conn++) { + conn = &conn_param[loop_conn]; + ble_addr_to_eui64(conn_addr.u8, conn->peer_address); + if((linkaddr_cmp(&dest_addr, &linkaddr_null) != 0) || (linkaddr_cmp(&dest_addr, &conn_addr) != 0)) { + for(loop_data = 0; loop_data < buf_len; loop_data += CONN_BLE_BUFFER_SIZE) { + data = &((uint8_t *)buf)[loop_data]; + data_len = MIN((buf_len - loop_data), CONN_BLE_BUFFER_SIZE); + if(loop_data == 0) { + result = send_frame(conn, data, data_len, BLE_DATA_PDU_LLID_DATA_MESSAGE); + } else { + result = send_frame(conn, data, data_len, BLE_DATA_PDU_LLID_DATA_FRAGMENT); + } + if(result != BLE_RESULT_OK) { + LOG_WARN("ble-hal: send was unsuccessful\n"); + return result; + } + } + } + } + return BLE_RESULT_OK; +} +/*---------------------------------------------------------------------------*/ +static ble_result_t +read_connection_interval(unsigned int conn_handle, unsigned int *conn_interval) +{ + ble_conn_param_t *conn = get_connection_for_handle(conn_handle); + if(conn == NULL) { + memset(conn_interval, 0x00, sizeof(uint16_t)); + return BLE_RESULT_ERROR; + } + memcpy(conn_interval, &conn->interval, sizeof(uint16_t)); + return BLE_RESULT_OK; +} +/*---------------------------------------------------------------------------*/ +const struct ble_hal_driver ble_hal = +{ + reset, + read_bd_addr, + read_buffer_size, + set_adv_param, + read_adv_channel_tx_power, + set_adv_data, + set_scan_resp_data, + set_adv_enable, + NULL, + NULL, + NULL, + NULL, + connection_update, + NULL, + send, + NULL, + read_connection_interval +}; +/*---------------------------------------------------------------------------*/ +static void +advertising_rx(ble_adv_param_t *param) +{ + uint8_t i; + uint8_t offset = 14; + uint8_t *rx_data; + ble_conn_param_t *c_param = &conn_param[0]; + rtimer_clock_t wakeup; + + while(RX_ENTRY_STATUS(param->rx_queue_current) == DATA_ENTRY_FINISHED) { + rx_data = RX_ENTRY_DATA_PTR(param->rx_queue_current); + + if(CMD_GET_STATUS(param->cmd_buf) == RF_CORE_RADIO_OP_STATUS_BLE_DONE_CONNECT) { + /* parsing connection parameter */ + for(i = 0; i < BLE_ADDR_SIZE; i++) { + c_param->peer_address[i] = rx_data[BLE_ADDR_SIZE + 1 - i]; + } + memcpy(&c_param->access_address, &rx_data[offset], 4); + memcpy(&c_param->crc_init_0, &rx_data[offset + 4], 1); + memcpy(&c_param->crc_init_1, &rx_data[offset + 5], 1); + memcpy(&c_param->crc_init_2, &rx_data[offset + 6], 1); + memcpy(&c_param->win_size, &rx_data[offset + 7], 1); + memcpy(&c_param->win_offset, &rx_data[offset + 8], 2); + memcpy(&c_param->interval, &rx_data[offset + 10], 2); + memcpy(&c_param->latency, &rx_data[offset + 12], 2); + memcpy(&c_param->timeout, &rx_data[offset + 14], 2); + memcpy(&c_param->channel_map, &rx_data[offset + 16], 5); + memcpy(&c_param->hop, &rx_data[offset + 21], 1); + memcpy(&c_param->sca, &rx_data[offset + 21], 1); + memcpy(&c_param->timestamp_rt, &rx_data[offset + 24], 4); + + /* convert all received timing values to rtimer ticks */ + + c_param->timestamp_rt = ticks_from_unit(c_param->timestamp_rt, TIME_UNIT_RF_CORE); + c_param->hop = c_param->hop & 0x1F; + c_param->sca = (c_param->sca >> 5) & 0x07; + + LOG_INFO("connection created: conn_int: %4u, latency: %3u, channel_map: %8llX\n", + c_param->interval, c_param->latency, c_param->channel_map); + + LOG_DBG("access address: 0x%08lX\n", c_param->access_address); + LOG_DBG("crc0: 0x%02X\n", c_param->crc_init_0); + LOG_DBG("crc1: 0x%02X\n", c_param->crc_init_1); + LOG_DBG("crc2: 0x%02X\n", c_param->crc_init_2); + LOG_DBG("win_size: %4u\n", c_param->win_size); + LOG_DBG("win_offset: %4u\n", c_param->win_offset); + LOG_DBG("interval: %4u\n", c_param->interval); + LOG_DBG("latency: %4u\n", c_param->latency); + LOG_DBG("timeout: %4u\n", c_param->timeout); + LOG_DBG("channel_map: %llX\n", c_param->channel_map); + + /* calculate the first anchor point + * (add an interval, because we skip the first connection event ) */ + wakeup = c_param->timestamp_rt + ticks_from_unit(c_param->win_offset, TIME_UNIT_1_25_MS) - CONN_WINDOW_WIDENING_TICKS; + wakeup += ticks_from_unit(c_param->interval, TIME_UNIT_1_25_MS) - CONN_PREPROCESSING_TIME_TICKS; + rtimer_set(&c_param->timer, wakeup, 0, connection_event_slave, (void *)c_param); + + /* initialization for the connection */ + c_param->counter = 0; + c_param->unmapped_channel = 0; + c_param->conn_handle = conn_counter; + c_param->active = 1; + conn_counter++; + LOG_INFO("BLE-HAL: connection (0x%04X) created\n", c_param->conn_handle); + } + + /* free current entry (clear BLE data length & reset status) */ + RX_ENTRY_DATA_LENGTH(param->rx_queue_current) = 0; + RX_ENTRY_STATUS(param->rx_queue_current) = DATA_ENTRY_PENDING; + param->rx_queue_current = RX_ENTRY_NEXT_ENTRY(param->rx_queue_current); + } +} +/*---------------------------------------------------------------------------*/ +static void +advertising_event(struct rtimer *t, void *ptr) +{ + ble_adv_param_t *param = (ble_adv_param_t *)ptr; + uint32_t wakeup; + + if(on() != BLE_RESULT_OK) { + LOG_ERR("BLE-HAL: advertising event: could not enable rf core\n"); + return; + } + + rf_ble_cmd_create_adv_params(param->param_buf, ¶m->rx_queue, + param->adv_data_len, param->adv_data, + param->scan_rsp_data_len, param->scan_rsp_data, + param->own_addr_type, (uint8_t *)BLE_ADDR_LOCATION); + + /* advertising on advertisement channel 1*/ + if(param->channel_map & BLE_ADV_CHANNEL_1_MASK) { + rf_ble_cmd_create_adv_cmd(param->cmd_buf, BLE_ADV_CHANNEL_1, + param->param_buf, param->output_buf); + rf_ble_cmd_send(param->cmd_buf); + rf_ble_cmd_wait(param->cmd_buf); + } + + off(); + advertising_rx(param); + + if(conn_param[0].active == 1) { + LOG_INFO("stop advertising\n"); + return; + } + + param->start_rt = param->start_rt + ticks_from_unit(param->adv_interval, TIME_UNIT_MS); + wakeup = adv_param.start_rt - ADV_PREPROCESSING_TIME_TICKS; + rtimer_set(¶m->timer, wakeup, 0, advertising_event, (void *)param); +} +/*---------------------------------------------------------------------------*/ +static void +update_data_channel(ble_conn_param_t *param) +{ + uint8_t i; + uint8_t j; + uint8_t remap_index; + /* perform the data channel selection according to BLE standard */ + + /* calculate unmapped channel*/ + param->unmapped_channel = (param->unmapped_channel + param->hop) % (BLE_DATA_CHANNEL_MAX + 1); + + /* map the calculated channel */ + if(param->channel_map & (1ULL << param->unmapped_channel)) { + /* channel is marked as used */ + param->mapped_channel = param->unmapped_channel; + } else { + remap_index = param->unmapped_channel % param->num_used_channels; + j = 0; + for(i = 0; i < (BLE_DATA_CHANNEL_MAX + 1); i++) { + if(param->channel_map & (1ULL << i)) { + if(j == remap_index) { + param->mapped_channel = i; + } + j++; + } + } + } +} +/*---------------------------------------------------------------------------*/ +static void +process_ll_ctrl_msg(ble_conn_param_t *conn, uint8_t input_len, uint8_t *input, uint8_t *output_len, uint8_t *output) +{ + uint8_t op_code = input[0]; + uint16_t interval; + uint16_t latency; + uint16_t timeout; + uint64_t channel_map = 0; + uint16_t instant = 0; + uint8_t i; + + if(op_code == BLE_LL_CONN_UPDATE_REQ) { + LOG_INFO("BLE-HAL: connection update request received\n"); + memcpy(&conn->conn_update_win_size, &input[1], 1); + memcpy(&conn->conn_update_win_offset, &input[2], 2); + memcpy(&conn->conn_update_interval, &input[4], 2); + memcpy(&conn->conn_update_latency, &input[6], 2); + memcpy(&conn->conn_update_timeout, &input[8], 2); + memcpy(&conn->conn_update_counter, &input[10], 2); + } else if(op_code == BLE_LL_CHANNEL_MAP_REQ) { + LOG_INFO("BLE-HAL: channel map update received\n"); + memcpy(&channel_map, &input[1], 5); + memcpy(&instant, &input[6], 2); + + conn->channel_update_channel_map = channel_map; + conn->channel_update_counter = instant; + conn->channel_update_num_used_channels = 0; + for(i = 0; i <= BLE_DATA_CHANNEL_MAX; i++) { + if(channel_map & (1ULL << i)) { + conn->channel_update_num_used_channels++; + } + } + } else if(op_code == BLE_LL_FEATURE_REQ) { + LOG_INFO("BLE-HAL: feature request received\n"); + output[0] = BLE_LL_FEATURE_RSP; + memset(&output[1], 0x00, 8); + *output_len = 9; + } else if(op_code == BLE_LL_VERSION_IND) { + LOG_INFO("BLE-HAL: version request received\n"); + output[0] = BLE_LL_VERSION_IND; + output[1] = 7; + memset(&output[2], 0xAA, 4); + *output_len = 6; + } else if(op_code == BLE_LL_CONN_PARAM_REQ) { + LOG_INFO("BLE-HAL: connection parameter request received\n"); + memcpy(&interval, &input[1], 2); /* use interval min */ + memcpy(&latency, &input[5], 2); + memcpy(&timeout, &input[7], 2); + connection_update(conn->conn_handle, interval, latency, timeout); + } else { + LOG_WARN("BLE-HAL: unknown LL control code: %02X\n", op_code); + } +} +/*---------------------------------------------------------------------------*/ +static void +connection_rx(ble_conn_param_t *param) +{ + uint8_t header_offset = 2; + uint8_t *rx_data; + uint16_t len; + uint8_t channel; + uint8_t frame_type; + uint8_t more_data; + uint8_t rssi; + linkaddr_t sender_addr; + rfc_bleMasterSlaveOutput_t *out_buf = (rfc_bleMasterSlaveOutput_t *)param->output_buf; + + uint8_t output_len = 0; + uint8_t output[26]; + + while(RX_ENTRY_STATUS(param->rx_queue_current) == DATA_ENTRY_FINISHED) { + rx_data = RX_ENTRY_DATA_PTR(param->rx_queue_current); + len = RX_ENTRY_DATA_LENGTH(param->rx_queue_current) - 6 - 2; /* last 8 bytes are status, timestamp, ... */ + channel = (rx_data[len + 3] & 0x3F); + frame_type = rx_data[0] & 0x03; + more_data = (rx_data[0] & 0x10) >> 4; + + if(frame_type == BLE_DATA_PDU_LLID_CONTROL) { + process_ll_ctrl_msg(param, (len - header_offset), &rx_data[header_offset], &output_len, output); + if(output_len > 0) { + send_frame(param, output, output_len, BLE_DATA_PDU_LLID_CONTROL); + } + } else if(frame_type == BLE_DATA_PDU_LLID_DATA_MESSAGE) { + packetbuf_clear(); + memcpy(packetbuf_dataptr(), &rx_data[header_offset], len); + packetbuf_set_datalen(len); + rssi = out_buf->lastRssi; + ble_addr_to_eui64(sender_addr.u8, param->peer_address); + packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi); + packetbuf_set_attr(PACKETBUF_ATTR_CHANNEL, channel); + packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &linkaddr_node_addr); + packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &sender_addr); + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME_BLE_RX_EVENT); + if((!more_data) || (len < CONN_BLE_BUFFER_SIZE)) { + NETSTACK_MAC.input(); + } + } else if(frame_type == BLE_DATA_PDU_LLID_DATA_FRAGMENT) { + memcpy((packetbuf_dataptr() + packetbuf_datalen()), &rx_data[header_offset], len); + packetbuf_set_datalen(packetbuf_datalen() + len); + if((!more_data) || (len < CONN_BLE_BUFFER_SIZE)) { + NETSTACK_MAC.input(); + } + } + + /* free current entry (clear BLE data length & reset status) */ + RX_ENTRY_DATA_LENGTH(param->rx_queue_current) = 0; + RX_ENTRY_STATUS(param->rx_queue_current) = DATA_ENTRY_PENDING; + param->rx_queue_current = RX_ENTRY_NEXT_ENTRY(param->rx_queue_current); + } +} +/*---------------------------------------------------------------------------*/ +static void +connection_event_slave(struct rtimer *t, void *ptr) +{ + + ble_conn_param_t *conn = (ble_conn_param_t *)ptr; + rfc_bleMasterSlaveOutput_t *output = (rfc_bleMasterSlaveOutput_t *)conn->output_buf; + uint8_t first_packet = 0; + rtimer_clock_t wakeup; + uint8_t i; + uint8_t tx_data = tx_queue_data_to_transmit(conn); + + if(conn->counter == 0) { + /* the slave skips connection event 0, because it is usually too early */ + conn->start_rt = conn->timestamp_rt + ticks_from_unit(conn->win_offset, TIME_UNIT_1_25_MS) - CONN_WINDOW_WIDENING_TICKS; + update_data_channel(conn); + first_packet = 1; + } + conn->counter++; + + /* connection timing */ + if(conn->counter == conn->conn_update_counter) { + conn->start_rt += ticks_from_unit(conn->interval + conn->conn_update_win_offset, TIME_UNIT_1_25_MS); + + conn->win_size = conn->conn_update_win_size; + conn->win_offset = conn->conn_update_win_offset; + conn->interval = conn->conn_update_interval; + conn->latency = conn->conn_update_latency; + conn->timeout = conn->conn_update_timeout; + conn->conn_update_win_size = 0; + conn->conn_update_win_offset = 0; + conn->conn_update_interval = 0; + conn->conn_update_latency = 0; + conn->conn_update_timeout = 0; + } else if(output->pktStatus.bTimeStampValid) { + conn->start_rt = ticks_from_unit(output->timeStamp, TIME_UNIT_RF_CORE) + + ticks_from_unit(conn->interval, TIME_UNIT_1_25_MS) - CONN_WINDOW_WIDENING_TICKS; + } else { + conn->start_rt += ticks_from_unit(conn->interval, TIME_UNIT_1_25_MS); + } + + /* connection channel */ + if(conn->channel_update_counter == conn->counter) { + conn->channel_map = conn->channel_update_channel_map; + conn->num_used_channels = conn->channel_update_num_used_channels; + conn->channel_update_counter = 0; + conn->channel_update_channel_map = 0; + conn->channel_update_num_used_channels = 0; + } + update_data_channel(conn); + + if(tx_data || (conn->skipped_events >= conn->latency) || (conn->counter < CONN_EVENT_LATENCY_THRESHOLD)) { + /* participating in the connection event */ + conn->skipped_events = 0; + rf_ble_cmd_create_slave_params(conn->param_buf, &conn->rx_queue, &conn->tx_queue, conn->access_address, + conn->crc_init_0, conn->crc_init_1, conn->crc_init_2, + ticks_to_unit(ticks_from_unit(conn->win_size, TIME_UNIT_1_25_MS), TIME_UNIT_RF_CORE), + ticks_to_unit(CONN_WINDOW_WIDENING_TICKS, TIME_UNIT_RF_CORE), first_packet); + + rf_ble_cmd_create_slave_cmd(conn->cmd_buf, conn->mapped_channel, conn->param_buf, conn->output_buf, + ticks_to_unit(conn->start_rt, TIME_UNIT_RF_CORE)); + + if(on() != BLE_RESULT_OK) { + LOG_ERR("connection_event: could not enable radio core\n"); + return; + } + + /* append TX buffers */ + for(i = 0; i < CONN_TX_BUFFERS_NUM; i++) { + if(TX_ENTRY_STATUS(conn->tx_buffers[i]) == DATA_ENTRY_QUEUED) { + TX_ENTRY_STATUS(conn->tx_buffers[i]) = DATA_ENTRY_PENDING; + rf_ble_cmd_add_data_queue_entry(&conn->tx_queue, conn->tx_buffers[i]); + } + } + rf_ble_cmd_send(conn->cmd_buf); + rf_ble_cmd_wait(conn->cmd_buf); + off(); + + if(CMD_GET_STATUS(conn->cmd_buf) != RF_CORE_RADIO_OP_STATUS_BLE_DONE_OK) { + LOG_DBG("command status: 0x%04X; connection event counter: %d, channel: %d\n", + CMD_GET_STATUS(conn->cmd_buf), conn->counter, conn->mapped_channel); + } + + /* free finished TX buffers */ + for(i = 0; i < CONN_TX_BUFFERS_NUM; i++) { + if(TX_ENTRY_STATUS(conn->tx_buffers[i]) == DATA_ENTRY_FINISHED) { + TX_ENTRY_STATUS(conn->tx_buffers[i]) = DATA_ENTRY_FREE; + TX_ENTRY_LENGTH(conn->tx_buffers[i]) = 0; + TX_ENTRY_NEXT_ENTRY(conn->tx_buffers[i]) = NULL; + } + } + } else { + /* skipping connection event */ + conn->skipped_events++; + output->pktStatus.bTimeStampValid = 0; + } + wakeup = conn->start_rt + ticks_from_unit(conn->interval, TIME_UNIT_1_25_MS) - CONN_PREPROCESSING_TIME_TICKS; + rtimer_set(&conn->timer, wakeup, 0, connection_event_slave, ptr); + process_post(&ble_hal_conn_rx_process, rx_data_event, ptr); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(ble_hal_conn_rx_process, ev, data) { + ble_conn_param_t *conn = (ble_conn_param_t *)data; + rfc_bleMasterSlaveOutput_t *output = (rfc_bleMasterSlaveOutput_t *)conn->output_buf; + uint8_t tx_buffers_sent; + PROCESS_BEGIN(); + LOG_DBG("BLE-HAL: conn rx process start\n"); + + while(1) { + PROCESS_WAIT_EVENT_UNTIL(ev == rx_data_event); + /* notify upper layers (L2CAP) when TX buffers were successfully transmitted */ + tx_buffers_sent = output->nTxEntryDone - conn->tx_buffers_sent; + if(tx_buffers_sent != 0) { + conn->tx_buffers_sent = output->nTxEntryDone; + packetbuf_set_datalen(0); + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME_BLE_TX_EVENT); + NETSTACK_MAC.input(); + } + + /* handle RX buffers */ + connection_rx(conn); + + /* generate an event if the connection parameter were updated */ + if(conn->counter == conn->conn_update_counter) { + packetbuf_set_datalen(0); + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME_BLE_CONNECTION_UPDATED); + NETSTACK_MAC.input(); + } + } + + PROCESS_END(); +} diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/ble-hal-cc26xx.h b/arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/ble-hal-cc26xx.h new file mode 100644 index 0000000000000000000000000000000000000000..41e71c6846b2d0d49e2a95709f9d4d3d6979fa5e --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/ble-hal-cc26xx.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017, Graz University of Technology + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * BLE radio hardware abstraction for the TI CC26XX controller + * + * \author + * Michael Spoerk <michael.spoerk@tugraz.at> + */ +/*---------------------------------------------------------------------------*/ + +#ifndef BLE_HAL_CC26XX_H_ +#define BLE_HAL_CC26XX_H_ + +#include "os/dev/ble-hal.h" + +extern const struct ble_hal_driver ble_hal; + +#endif /* BLE_HAL_CC26XX_H_ */ diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/rf-ble-cmd.c b/arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/rf-ble-cmd.c new file mode 100644 index 0000000000000000000000000000000000000000..cde42f99b7fae41d49d009c9e7494db374211485 --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/rf-ble-cmd.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2017, Graz University of Technology + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * BLE commands for the TI CC26xx BLE radio. + * These functions are specific to the TI CC26xx and cannot be + * reused by other BLE radios. + * + * \author + * Michael Spoerk <michael.spoerk@tugraz.at> + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include "rf_ble_cmd.h" +#include "rf-core/rf-core.h" +#include "rf-core/ble-hal/rf-ble-cmd.h" + +/*---------------------------------------------------------------------------*/ +#include "sys/log.h" +#define LOG_MODULE "BLE-RADIO" +#define LOG_LEVEL LOG_LEVEL_MAIN +/*---------------------------------------------------------------------------*/ +#define CMD_GET_STATUS(X) (((rfc_radioOp_t *)X)->status) +/*---------------------------------------------------------------------------*/ +/* values for a selection of available TX powers (values from SmartRF Studio) */ +/*static uint16_t tx_power = 0x9330; / * +5 dBm * / */ +static uint16_t tx_power = 0x3161; /* 0 dBm */ +/*static uint16_t tx_power = 0x0CCB; / * -15 dBm * / */ +/*---------------------------------------------------------------------------*/ +/* BLE overrides */ +static uint32_t ble_overrides[] = { + 0x00364038, /* Synth: Set RTRIM (POTAILRESTRIM) to 6 */ + 0x000784A3, /* Synth: Set FREF = 3.43 MHz (24 MHz / 7) */ + 0xA47E0583, /* Synth: Set loop bandwidth after lock to 80 kHz (K2) */ + 0xEAE00603, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, LSB) */ + 0x00010623, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, MSB) */ + 0x00456088, /* Adjust AGC reference level */ + 0x008F88B3, /* GPIO mode: https://e2e.ti.com/support/wireless_connectivity/proprietary_sub_1_ghz_simpliciti/f/156/t/488244?*/ + 0xFFFFFFFF, /* End of override list */ +}; +/*---------------------------------------------------------------------------*/ +unsigned short +rf_ble_cmd_send(uint8_t *command) +{ + uint32_t cmdsta; + rfc_radioOp_t *cmd = (rfc_radioOp_t *)command; + + if(rf_core_send_cmd((uint32_t)cmd, &cmdsta) != RF_CORE_CMD_OK) { + LOG_ERR("rf_ble_cmd_send() could not send cmd. status: 0x%04X\n", + CMD_GET_STATUS(cmd)); + return RF_BLE_CMD_ERROR; + } + return RF_BLE_CMD_OK; +} +/*---------------------------------------------------------------------------*/ +unsigned short +rf_ble_cmd_wait(uint8_t *command) +{ + rfc_radioOp_t *cmd = (rfc_radioOp_t *)command; + if(rf_core_wait_cmd_done((void *)cmd) != RF_CORE_CMD_OK) { + LOG_ERR("rf_ble_cmd_wait() could not wait. status: 0x%04X\n", + CMD_GET_STATUS(cmd)); + return RF_BLE_CMD_ERROR; + } + return RF_BLE_CMD_OK; +} +/*---------------------------------------------------------------------------*/ +unsigned short +rf_ble_cmd_setup_ble_mode(void) +{ + rfc_CMD_RADIO_SETUP_t cmd; + + /* Create radio setup command */ + rf_core_init_radio_op((rfc_radioOp_t *)&cmd, sizeof(cmd), CMD_RADIO_SETUP); + + cmd.txPower = tx_power; + cmd.pRegOverride = ble_overrides; + cmd.mode = 0; + + /* Send Radio setup to RF Core */ + if(rf_ble_cmd_send((uint8_t *)&cmd) != RF_BLE_CMD_OK) { + return RF_BLE_CMD_ERROR; + } + + /* Wait until radio setup is done */ + return rf_ble_cmd_wait((uint8_t *)&cmd); +} +/*---------------------------------------------------------------------------*/ +/* ADVERTISING functions */ +void +rf_ble_cmd_create_adv_cmd(uint8_t *command, uint8_t channel, + uint8_t *param, uint8_t *output) +{ + rfc_CMD_BLE_ADV_t *c = (rfc_CMD_BLE_ADV_t *)command; + + memset(c, 0x00, sizeof(rfc_CMD_BLE_ADV_t)); + c->commandNo = CMD_BLE_ADV; + c->condition.rule = COND_NEVER; + c->whitening.bOverride = 0; + c->channel = channel; + c->pParams = (rfc_bleAdvPar_t *)param; + c->startTrigger.triggerType = TRIG_NOW; + c->pOutput = (rfc_bleAdvOutput_t *)output; +} +/*---------------------------------------------------------------------------*/ +void +rf_ble_cmd_create_adv_params(uint8_t *param, dataQueue_t *rx_queue, + uint8_t adv_data_len, uint8_t *adv_data, + uint8_t scan_resp_data_len, uint8_t *scan_resp_data, + ble_addr_type_t own_addr_type, uint8_t *own_addr) +{ + rfc_bleAdvPar_t *p = (rfc_bleAdvPar_t *)param; + + memset(p, 0x00, sizeof(rfc_bleAdvPar_t)); + + p->pRxQ = rx_queue; + p->rxConfig.bAutoFlushIgnored = 1; + p->rxConfig.bAutoFlushCrcErr = 0; + p->rxConfig.bAutoFlushEmpty = 1; + p->rxConfig.bIncludeLenByte = 1; + p->rxConfig.bIncludeCrc = 0; + p->rxConfig.bAppendRssi = 1; + p->rxConfig.bAppendStatus = 1; + p->rxConfig.bAppendTimestamp = 1; + p->advConfig.advFilterPolicy = 0; + p->advConfig.bStrictLenFilter = 0; + p->advConfig.deviceAddrType = own_addr_type; + p->pDeviceAddress = (uint16_t *)own_addr; + p->advLen = adv_data_len; + p->scanRspLen = scan_resp_data_len; + p->pAdvData = adv_data; + p->pScanRspData = scan_resp_data; + p->endTrigger.triggerType = TRIG_NEVER; +} +/*---------------------------------------------------------------------------*/ +/* CONNECTION slave functions */ +/*---------------------------------------------------------------------------*/ +void +rf_ble_cmd_create_slave_cmd(uint8_t *cmd, uint8_t channel, uint8_t *params, + uint8_t *output, uint32_t start_time) +{ + rfc_CMD_BLE_SLAVE_t *c = (rfc_CMD_BLE_SLAVE_t *)cmd; + + memset(c, 0x00, sizeof(rfc_CMD_BLE_SLAVE_t)); + + c->commandNo = CMD_BLE_SLAVE; + c->condition.rule = COND_NEVER; + c->whitening.bOverride = 0; + c->channel = channel; + c->pParams = (rfc_bleSlavePar_t *)params; + c->startTrigger.triggerType = TRIG_ABSTIME; + c->startTrigger.pastTrig = 0; + c->startTime = start_time; + c->pOutput = (rfc_bleMasterSlaveOutput_t *)output; +} +/*---------------------------------------------------------------------------*/ +void +rf_ble_cmd_create_slave_params(uint8_t *params, dataQueue_t *rx_queue, + dataQueue_t *tx_queue, uint32_t access_address, + uint8_t crc_init_0, uint8_t crc_init_1, + uint8_t crc_init_2, uint32_t win_size, + uint32_t window_widening, uint8_t first_packet) +{ + rfc_bleSlavePar_t *p = (rfc_bleSlavePar_t *)params; + + p->pRxQ = rx_queue; + p->pTxQ = tx_queue; + p->rxConfig.bAutoFlushIgnored = 1; + p->rxConfig.bAutoFlushCrcErr = 1; + p->rxConfig.bAutoFlushEmpty = 1; + p->rxConfig.bIncludeLenByte = 1; + p->rxConfig.bIncludeCrc = 0; + p->rxConfig.bAppendRssi = 1; + p->rxConfig.bAppendStatus = 1; + p->rxConfig.bAppendTimestamp = 1; + + if(first_packet) { + /* set parameters for first packet according to TI Technical Reference Manual */ + p->seqStat.lastRxSn = 1; + p->seqStat.lastTxSn = 1; + p->seqStat.nextTxSn = 0; + p->seqStat.bFirstPkt = 1; + p->seqStat.bAutoEmpty = 0; + p->seqStat.bLlCtrlTx = 0; + p->seqStat.bLlCtrlAckRx = 0; + p->seqStat.bLlCtrlAckPending = 0; + } + + p->maxNack = 0; + p->maxPkt = 0; + p->accessAddress = access_address; + p->crcInit0 = crc_init_0; + p->crcInit1 = crc_init_1; + p->crcInit2 = crc_init_2; + p->timeoutTrigger.triggerType = TRIG_REL_START; + if(first_packet) { + p->timeoutTime = (uint32_t)(10 * win_size); + } else { + p->timeoutTime = (uint32_t)(win_size + 2 * window_widening); + } + p->endTrigger.triggerType = TRIG_NEVER; +} +/*---------------------------------------------------------------------------*/ +/* DATA queue functions */ +/*---------------------------------------------------------------------------*/ +unsigned short +rf_ble_cmd_add_data_queue_entry(dataQueue_t *q, uint8_t *e) +{ + uint32_t cmdsta; + + rfc_CMD_ADD_DATA_ENTRY_t cmd; + cmd.commandNo = CMD_ADD_DATA_ENTRY; + cmd.pQueue = q; + cmd.pEntry = e; + + if(rf_core_send_cmd((uint32_t)&cmd, &cmdsta) != RF_CORE_CMD_OK) { + LOG_ERR("could not add entry to data queue. status: 0x%04X\n", + CMD_GET_STATUS(&cmd)); + return RF_BLE_CMD_ERROR; + } + return RF_BLE_CMD_OK; +} diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/rf-ble-cmd.h b/arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/rf-ble-cmd.h new file mode 100644 index 0000000000000000000000000000000000000000..d8a86f798da8b5c834b83cc070ea8481a6dabfea --- /dev/null +++ b/arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/rf-ble-cmd.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2017, Graz University of Technology + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * BLE commands for the TI CC26xx BLE radio. + * These functions are specific to the TI CC26xx and cannot be + * reused by other BLE radios. + * + * \author + * Michael Spoerk <michael.spoerk@tugraz.at> + */ +/*---------------------------------------------------------------------------*/ + +#ifndef RF_BLE_CMD_H_ +#define RF_BLE_CMD_H_ + +#include "os/dev/ble-hal.h" +#include "../../ble-addr.h" +#include "rf_common_cmd.h" + +#define RF_BLE_CMD_OK 1 +#define RF_BLE_CMD_ERROR 0 + +/*---------------------------------------------------------------------------*/ +/** + * \brief Sends a BLE radio command to the radio + * \param cmd A pointer to the command to be send + * \return RF_CORE_CMD_OK or RF_CORE_CMD_ERROR + */ +unsigned short rf_ble_cmd_send(uint8_t *cmd); + +/*---------------------------------------------------------------------------*/ +/** + * \brief Waits for a running BLE radio command to be finished + * \param cmd A pointer to the running command + * \return RF_CORE_CMD_OK or RF_CORE_CMD_ERROR + */ +unsigned short rf_ble_cmd_wait(uint8_t *cmd); + +/*---------------------------------------------------------------------------*/ +/** + * \brief Initializes the radio core to be used as a BLE radio + * \return RF_CORE_CMD_OK or RF_CORE_CMD_ERROR + */ +unsigned short rf_ble_cmd_setup_ble_mode(void); + +/*---------------------------------------------------------------------------*/ +/** + * \brief Creates a BLE radio command structure that enables + * BLE advertisement when sent to the radio core + * \param command A pointer to command that is created + * \param channel The BLE advertisement channel used for advertisement + * \param param A pointer to the radio command parameters + * \param output A pointer to the radio command output + */ +void rf_ble_cmd_create_adv_cmd(uint8_t *command, uint8_t channel, + uint8_t *param, uint8_t *output); + +/*---------------------------------------------------------------------------*/ +/** + * \brief Creates BLE radio command parameters that are used to enable + * BLE advertisement on the radio core + * \param param A pointer to parameter structure that is created + * \param rx_queue A pointer to the RX queue that is used + * \param adv_data_len + * The length of the advertisement data + * \param adv_data A pointer to the advertisement data that is advertised + * \param scan_resp_data_len + * The length of the scan response data + * \param scan_resp_data + * A pointer to the scan response data + * \param own_addr_type + * Either BLE_ADDR_TYPE_PUBLIC or BLE_ADDR_TYPE_RANDOM + * \param own_addr A pointer to the device address that is used as own address + */ +void rf_ble_cmd_create_adv_params(uint8_t *param, dataQueue_t *rx_queue, + uint8_t adv_data_len, uint8_t *adv_data, + uint8_t scan_resp_data_len, uint8_t *scan_resp_data, + ble_addr_type_t own_addr_type, uint8_t *own_addr); + +/*---------------------------------------------------------------------------*/ +/** + * \brief Creates a BLE radio command structure that sets up a single + * BLE connection event when sent to the radio core + * \param cmd A pointer to command that is created + * \param channel The BLE data channel used for the connection event + * \param param A pointer to the radio command parameters + * \param output A pointer to the radio command output + * \param start_time + * The time in rf_core_ticks when the connection event will start + */ +void rf_ble_cmd_create_slave_cmd(uint8_t *cmd, uint8_t channel, uint8_t *param, + uint8_t *output, uint32_t start_time); + +/*---------------------------------------------------------------------------*/ +/** + * \brief Creates BLE radio command parameters that are used to setup a single + * BLE connection event on the radio core + * \param param A pointer to parameter structure that is created + * \param rx_queue A pointer to the RX queue that is used + * \param tx_queue A pointer to the TX queue that is used + * \param access_address + * The access address of the used BLE connection + * \param crc_init_0 + * Part of the initialization of the CRC checksum + * \param crc_init_1 + * Part of the initialization of the CRC checksum + * \param crc_init_2 + * Part of the initialization of the CRC checksum + * \param win_size The window size parameter of the BLE connection event + * \param window_widening + * The window widening parameter used for this connection event + * \param first_packet + * 1 for the first packet of the BLE connection so that the + * connection is properly initialized + */ +void rf_ble_cmd_create_slave_params(uint8_t *param, dataQueue_t *rx_queue, + dataQueue_t *tx_queue, uint32_t access_address, + uint8_t crc_init_0, uint8_t crc_init_1, + uint8_t crc_init_2, uint32_t win_size, + uint32_t window_widening, uint8_t first_packet); + +/*---------------------------------------------------------------------------*/ +/** + * \brief Adds a data buffer to a BLE transmission queue + * \param q A pointer to BLE transmission queue where the buffer + * should be added + * \param e A pointer to the data buffer that is added + */ +unsigned short rf_ble_cmd_add_data_queue_entry(dataQueue_t *q, uint8_t *e); + +#endif /* RF_BLE_CMD_H_ */ diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/ieee-mode.c b/arch/cpu/cc26xx-cc13xx/rf-core/ieee-mode.c index d4c1c27e58601bad3b1c5f4ee9eebbfbc66d00e5..a5479a4ee577391cf0661195227558441afec87f 100644 --- a/arch/cpu/cc26xx-cc13xx/rf-core/ieee-mode.c +++ b/arch/cpu/cc26xx-cc13xx/rf-core/ieee-mode.c @@ -167,6 +167,9 @@ static uint8_t rf_stats[16] = { 0 }; /* How long to wait for the RF to react on CMD_ABORT: around 1 msec */ #define RF_TURN_OFF_WAIT_TIMEOUT (RTIMER_SECOND >> 10) +/* How long to wait for the RF to finish TX of a packet or an ACK */ +#define TX_FINISH_WAIT_TIMEOUT (RTIMER_SECOND >> 7) + #define LIMITED_BUSYWAIT(cond, timeout) do { \ rtimer_clock_t end_time = RTIMER_NOW() + timeout; \ while(cond) { \ @@ -206,7 +209,7 @@ static const output_config_t output_power[] = { #define OUTPUT_POWER_UNKNOWN 0xFFFF /* Default TX Power - position in output_power[] */ -const output_config_t *tx_power_current = &output_power[0]; +static const output_config_t *tx_power_current = &output_power[0]; /*---------------------------------------------------------------------------*/ static volatile int8_t last_rssi = 0; static volatile uint8_t last_corr_lqi = 0; @@ -260,6 +263,20 @@ static uint8_t rx_buf_1[RX_BUF_SIZE] CC_ALIGN(4); static uint8_t rx_buf_2[RX_BUF_SIZE] CC_ALIGN(4); static uint8_t rx_buf_3[RX_BUF_SIZE] CC_ALIGN(4); +#define RX_BUF_INCLUDE_CRC 1 +#define RX_BUF_INCLUDE_RSSI 1 +#define RX_BUF_INCLUDE_CORR 1 +#define RX_BUF_INCLUDE_TIMESTAMP 1 + +/* The size of the metadata (excluding the packet length field) */ +#define RX_BUF_METADATA_SIZE \ + (2 * RX_BUF_INCLUDE_CRC + RX_BUF_INCLUDE_RSSI + RX_BUF_INCLUDE_CORR + 4 * RX_BUF_INCLUDE_TIMESTAMP) + +/* The offset of the packet length in a rx buffer */ +#define RX_BUF_LENGTH_OFFSET sizeof(rfc_dataEntry_t) +/* The offset of the packet data in a rx buffer */ +#define RX_BUF_DATA_OFFSET (RX_BUF_LENGTH_OFFSET + 1) + /* The RX Data Queue */ static dataQueue_t rx_data_queue = { 0 }; @@ -562,22 +579,22 @@ init_rx_buffers(void) entry = (rfc_dataEntry_t *)rx_buf_0; entry->pNextEntry = rx_buf_1; entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE; - entry->length = sizeof(rx_buf_0) - 8; + entry->length = sizeof(rx_buf_0) - sizeof(*entry); entry = (rfc_dataEntry_t *)rx_buf_1; entry->pNextEntry = rx_buf_2; entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE; - entry->length = sizeof(rx_buf_0) - 8; + entry->length = sizeof(rx_buf_0) - sizeof(*entry); entry = (rfc_dataEntry_t *)rx_buf_2; entry->pNextEntry = rx_buf_3; entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE; - entry->length = sizeof(rx_buf_0) - 8; + entry->length = sizeof(rx_buf_0) - sizeof(*entry); entry = (rfc_dataEntry_t *)rx_buf_3; entry->pNextEntry = rx_buf_0; entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE; - entry->length = sizeof(rx_buf_0) - 8; + entry->length = sizeof(rx_buf_0) - sizeof(*entry); } /*---------------------------------------------------------------------------*/ static void @@ -598,11 +615,11 @@ init_rf_params(void) cmd->rxConfig.bAutoFlushCrc = 1; cmd->rxConfig.bAutoFlushIgn = 0; cmd->rxConfig.bIncludePhyHdr = 0; - cmd->rxConfig.bIncludeCrc = 1; - cmd->rxConfig.bAppendRssi = 1; - cmd->rxConfig.bAppendCorrCrc = 1; + cmd->rxConfig.bIncludeCrc = RX_BUF_INCLUDE_CRC; + cmd->rxConfig.bAppendRssi = RX_BUF_INCLUDE_RSSI; + cmd->rxConfig.bAppendCorrCrc = RX_BUF_INCLUDE_CORR; cmd->rxConfig.bAppendSrcInd = 0; - cmd->rxConfig.bAppendTimestamp = 1; + cmd->rxConfig.bAppendTimestamp = RX_BUF_INCLUDE_TIMESTAMP; cmd->pRxQ = &rx_data_queue; cmd->pOutput = (rfc_ieeeRxOutput_t *)rf_stats; @@ -697,7 +714,7 @@ rx_off(void) } /* Wait for ongoing ACK TX to finish */ - while(transmitting()); + LIMITED_BUSYWAIT(transmitting(), TX_FINISH_WAIT_TIMEOUT); /* Send a CMD_ABORT command to RF Core */ if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &cmd_status) != RF_CORE_CMD_OK) { @@ -1076,15 +1093,15 @@ read_frame(void *buf, unsigned short buf_len) return 0; } - if(rx_read_entry[8] < 4) { - PRINTF("RF: too short\n"); + len = rx_read_entry[RX_BUF_LENGTH_OFFSET]; + if(len <= RX_BUF_METADATA_SIZE) { + PRINTF("RF: too short!"); release_data_entry(); return 0; } - len = rx_read_entry[8] - 8; - + len -= RX_BUF_METADATA_SIZE; if(len > buf_len) { PRINTF("RF: too long\n"); @@ -1092,13 +1109,13 @@ read_frame(void *buf, unsigned short buf_len) return 0; } - memcpy(buf, (char *)&rx_read_entry[9], len); + memcpy(buf, (uint8_t *)rx_read_entry + RX_BUF_DATA_OFFSET, len); - last_rssi = (int8_t)rx_read_entry[9 + len + 2]; - last_corr_lqi = (uint8_t)rx_read_entry[9 + len + 3] & STATUS_CORRELATION; + last_rssi = (int8_t)rx_read_entry[RX_BUF_DATA_OFFSET + len + 2]; + last_corr_lqi = (uint8_t)rx_read_entry[RX_BUF_DATA_OFFSET + len + 3] & STATUS_CORRELATION; /* get the timestamp */ - memcpy(&rat_timestamp, (char *)rx_read_entry + 9 + len + 4, 4); + memcpy(&rat_timestamp, (uint8_t *)rx_read_entry + RX_BUF_DATA_OFFSET + len + 4, 4); last_packet_timestamp = calc_last_packet_timestamp(rat_timestamp); @@ -1140,7 +1157,7 @@ channel_clear(void) * * We could probably even simply return that the channel is clear */ - while(transmitting()); + LIMITED_BUSYWAIT(transmitting(), TX_FINISH_WAIT_TIMEOUT); } else { was_off = 1; if(on() != RF_CORE_CMD_OK) { @@ -1297,7 +1314,7 @@ off(void) return RF_CORE_CMD_OK; } - while(transmitting()); + LIMITED_BUSYWAIT(transmitting(), TX_FINISH_WAIT_TIMEOUT); /* stopping the rx explicitly results in lower sleep-mode power usage */ rx_off(); diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/prop-mode.c b/arch/cpu/cc26xx-cc13xx/rf-core/prop-mode.c index 61581f20ad460314979b2c412740c5195b32dea1..f9f49e9a0da5c1b55a7dc93e4e0f02b7b41057db 100644 --- a/arch/cpu/cc26xx-cc13xx/rf-core/prop-mode.c +++ b/arch/cpu/cc26xx-cc13xx/rf-core/prop-mode.c @@ -203,7 +203,7 @@ extern const prop_mode_tx_power_config_t TX_POWER_DRIVER[]; #define OUTPUT_POWER_UNKNOWN 0xFFFF /* Default TX Power - position in output_power[] */ -const prop_mode_tx_power_config_t *tx_power_current = &TX_POWER_DRIVER[1]; +static const prop_mode_tx_power_config_t *tx_power_current = &TX_POWER_DRIVER[1]; /*---------------------------------------------------------------------------*/ #ifdef PROP_MODE_CONF_LO_DIVIDER #define PROP_MODE_LO_DIVIDER PROP_MODE_CONF_LO_DIVIDER diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/rf-ble.c b/arch/cpu/cc26xx-cc13xx/rf-core/rf-ble.c index 3faf75d25fab915ce4e2325693f43628a1eed8a3..e5a38cac7c75a48da71453c49da5c25527926e20 100644 --- a/arch/cpu/cc26xx-cc13xx/rf-core/rf-ble.c +++ b/arch/cpu/cc26xx-cc13xx/rf-core/rf-ble.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2017, University of Bristol - http://www.bristol.ac.uk/ * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -71,7 +72,7 @@ #define BLE_ADV_TYPE_DEVINFO 0x01 #define BLE_ADV_TYPE_NAME 0x09 #define BLE_ADV_TYPE_MANUFACTURER 0xFF -#define BLE_ADV_NAME_BUF_LEN 32 +#define BLE_ADV_NAME_BUF_LEN BLE_ADV_MAX_SIZE #define BLE_ADV_PAYLOAD_BUF_LEN 64 #define BLE_UUID_SIZE 16 /*---------------------------------------------------------------------------*/ @@ -82,8 +83,6 @@ static uint8_t payload[BLE_ADV_PAYLOAD_BUF_LEN]; static int p = 0; static int i; /*---------------------------------------------------------------------------*/ -static uint16_t tx_power = 0x9330; -/*---------------------------------------------------------------------------*/ /* BLE beacond config */ static struct ble_beacond_config { clock_time_t interval; @@ -108,6 +107,38 @@ static uint32_t ble_overrides[] = { 0xFFFFFFFF, /* End of override list */ }; /*---------------------------------------------------------------------------*/ +/* TX Power dBm lookup table - values from SmartRF Studio */ +typedef struct output_config { + radio_value_t dbm; + uint16_t tx_power; /* Value for the CMD_RADIO_SETUP.txPower field */ +} output_config_t; + +static const output_config_t output_power[] = { + { 5, 0x9330 }, + { 4, 0x9324 }, + { 3, 0x5a1c }, + { 2, 0x4e18 }, + { 1, 0x4214 }, + { 0, 0x3161 }, + { -3, 0x2558 }, + { -6, 0x1d52 }, + { -9, 0x194e }, + { -12, 0x144b }, + { -15, 0x0ccb }, + { -18, 0x0cc9 }, + { -21, 0x0cc7 }, +}; + +#define OUTPUT_CONFIG_COUNT (sizeof(output_power) / sizeof(output_config_t)) + +/* Max and Min Output Power in dBm */ +#define OUTPUT_POWER_MIN (output_power[OUTPUT_CONFIG_COUNT - 1].dbm) +#define OUTPUT_POWER_MAX (output_power[0].dbm) +#define OUTPUT_POWER_UNKNOWN 0xFFFF + +/* Default TX Power - position in output_power[] */ +static const output_config_t *tx_power_current = &output_power[0]; +/*---------------------------------------------------------------------------*/ PROCESS(rf_ble_beacon_process, "CC13xx / CC26xx RF BLE Beacon Process"); /*---------------------------------------------------------------------------*/ static int @@ -132,7 +163,7 @@ send_ble_adv_nc(int channel, uint8_t *adv_payload, int adv_payload_len) cmd.channel = channel; /* Set up BLE Advertisement parameters */ - params->pDeviceAddress = (uint16_t *)&linkaddr_node_addr.u8[LINKADDR_SIZE - 2]; + params->pDeviceAddress = (uint16_t *)BLE_ADDRESS_PTR; params->endTrigger.triggerType = TRIG_NEVER; params->endTime = TRIG_NEVER; @@ -157,6 +188,33 @@ send_ble_adv_nc(int channel, uint8_t *adv_payload, int adv_payload_len) return RF_CORE_CMD_OK; } /*---------------------------------------------------------------------------*/ +/* Returns the current TX power in dBm */ +radio_value_t +rf_ble_get_tx_power(void) +{ + return tx_power_current->dbm; +} +/*---------------------------------------------------------------------------*/ +/* + * Set TX power to 'at least' power dBm + * This works with a lookup table. If the value of 'power' does not exist in + * the lookup table, TXPOWER will be set to the immediately higher available + * value + */ +void +rf_ble_set_tx_power(radio_value_t power) +{ + int i; + + /* First, find the correct setting and save it */ + for(i = OUTPUT_CONFIG_COUNT - 1; i >= 0; --i) { + if(power <= output_power[i].dbm) { + tx_power_current = &output_power[i]; + break; + } + } +} +/*---------------------------------------------------------------------------*/ void rf_ble_beacond_config(clock_time_t interval, const char *name) { @@ -211,7 +269,6 @@ rf_ble_beacond_stop() { process_exit(&rf_ble_beacon_process); } -/*---------------------------------------------------------------------------*/ static uint8_t rf_radio_setup() { @@ -223,7 +280,7 @@ rf_radio_setup() /* Create radio setup command */ rf_core_init_radio_op((rfc_radioOp_t *)&cmd, sizeof(cmd), CMD_RADIO_SETUP); - cmd.txPower = tx_power; + cmd.txPower = tx_power_current->tx_power; cmd.pRegOverride = ble_overrides; cmd.config.frontEndMode = RF_CORE_RADIO_SETUP_FRONT_END_MODE; cmd.config.biasMode = RF_CORE_RADIO_SETUP_BIAS_MODE; @@ -246,13 +303,114 @@ rf_radio_setup() return RF_CORE_CMD_OK; } /*---------------------------------------------------------------------------*/ -PROCESS_THREAD(rf_ble_beacon_process, ev, data) +/*---------------------------------------------------------------------------*/ +void +rf_ble_beacon_single(uint8_t channel, uint8_t *data, uint8_t len) { - uint8_t was_on; - int j; uint32_t cmd_status; bool interrupts_disabled; + uint8_t j, channel_selected; + uint8_t was_on; + + /* Adhere to the maximum BLE advertisement payload size */ + if(len > BLE_ADV_NAME_BUF_LEN) { + len = BLE_ADV_NAME_BUF_LEN; + } + + /* + * Under ContikiMAC, some IEEE-related operations will be called from an + * interrupt context. We need those to see that we are in BLE mode. + */ + interrupts_disabled = ti_lib_int_master_disable(); + ble_mode_on = RF_BLE_ACTIVE; + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } + + /* + * First, determine our state: + * + * If we are running CSMA, we are likely in IEEE RX mode. We need to + * abort the IEEE BG Op before entering BLE mode. + * If we are ContikiMAC, we are likely off, in which case we need to + * boot the CPE before entering BLE mode + */ + was_on = rf_core_is_accessible(); + + if(was_on) { + /* + * We were on: If we are in the process of receiving a frame, abort the + * BLE beacon burst. Otherwise, terminate the primary radio Op so we + * can switch to BLE mode + */ + if(NETSTACK_RADIO.receiving_packet()) { + PRINTF("rf_ble_beacon_single: We were receiving\n"); + + /* Abort this pass */ + return; + } + + rf_core_primary_mode_abort(); + } else { + + oscillators_request_hf_xosc(); + + /* We were off: Boot the CPE */ + if(rf_core_boot() != RF_CORE_CMD_OK) { + /* Abort this pass */ + PRINTF("rf_ble_beacon_single: rf_core_boot() failed\n"); + return; + } + + oscillators_switch_to_hf_xosc(); + + /* Enter BLE mode */ + if(rf_radio_setup() != RF_CORE_CMD_OK) { + /* Continue so we can at least try to restore our previous state */ + PRINTF("rf_ble_beacon_single: Error entering BLE mode\n"); + } else { + + for(j = 0; j < 3; j++) { + channel_selected = (channel >> j) & 0x01; + if(channel_selected == 1) { + if(send_ble_adv_nc(37 + j, data, len) != RF_CORE_CMD_OK) { + /* Continue... */ + PRINTF("rf_ble_beacon_single: Channel=%d, " + "Error advertising\n", 37 + j); + } + } + } + } + + /* Send a CMD_STOP command to RF Core */ + if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_STOP), &cmd_status) != RF_CORE_CMD_OK) { + /* Continue... */ + PRINTF("rf_ble_beacon_single: status=0x%08lx\n", cmd_status); + } + if(was_on) { + /* We were on, go back to previous primary mode */ + rf_core_primary_mode_restore(); + } else { + /* We were off. Shut back off */ + rf_core_power_down(); + + /* Switch HF clock source to the RCOSC to preserve power */ + oscillators_switch_to_hf_rc(); + } + + interrupts_disabled = ti_lib_int_master_disable(); + + ble_mode_on = RF_BLE_IDLE; + + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(rf_ble_beacon_process, ev, data) +{ PROCESS_BEGIN(); while(1) { @@ -278,115 +436,21 @@ PROCESS_THREAD(rf_ble_beacon_process, ev, data) strlen(beacond_config.adv_name)); p += strlen(beacond_config.adv_name); + /* + * Send BLE_ADV_MESSAGES beacon bursts. Each burst on all three + * channels, with a BLE_ADV_DUTY_CYCLE interval between bursts + */ for(i = 0; i < BLE_ADV_MESSAGES; i++) { - /* - * Under ContikiMAC, some IEEE-related operations will be called from an - * interrupt context. We need those to see that we are in BLE mode. - */ - interrupts_disabled = ti_lib_int_master_disable(); - ble_mode_on = RF_BLE_ACTIVE; - if(!interrupts_disabled) { - ti_lib_int_master_enable(); - } - /* - * Send BLE_ADV_MESSAGES beacon bursts. Each burst on all three - * channels, with a BLE_ADV_DUTY_CYCLE interval between bursts - * - * First, determine our state: - * - * If we are running CSMA, we are likely in IEEE RX mode. We need to - * abort the IEEE BG Op before entering BLE mode. - * If we are ContikiMAC, we are likely off, in which case we need to - * boot the CPE before entering BLE mode - */ - was_on = rf_core_is_accessible(); - - if(was_on) { - /* - * We were on: If we are in the process of receiving a frame, abort the - * BLE beacon burst. Otherwise, terminate the primary radio Op so we - * can switch to BLE mode - */ - if(NETSTACK_RADIO.receiving_packet()) { - PRINTF("rf_ble_beacon_process: We were receiving\n"); - - /* Abort this pass */ - break; - } + rf_ble_beacon_single(BLE_ADV_CHANNEL_ALL, payload, p); - rf_core_primary_mode_abort(); - } else { - /* Request the HF XOSC to source the HF clock. */ - oscillators_request_hf_xosc(); - - /* We were off: Boot the CPE */ - if(rf_core_boot() != RF_CORE_CMD_OK) { - PRINTF("rf_ble_beacon_process: rf_core_boot() failed\n"); - - /* Abort this pass */ - break; - } - - /* Trigger a switch to the XOSC, so that we can use the FS */ - oscillators_switch_to_hf_xosc(); - } - - /* Enter BLE mode */ - if(rf_radio_setup() != RF_CORE_CMD_OK) { - PRINTF("cc26xx_rf_ble_beacon_process: Error entering BLE mode\n"); - /* Continue so we can at least try to restore our previous state */ - } else { - /* Send advertising packets on all 3 advertising channels */ - for(j = 37; j <= 39; j++) { - if(send_ble_adv_nc(j, payload, p) != RF_CORE_CMD_OK) { - PRINTF("cc26xx_rf_ble_beacon_process: Channel=%d, " - "Error advertising\n", j); - /* Break the loop, but don't return just yet */ - break; - } - } - } - - /* Send a CMD_STOP command to RF Core */ - if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_STOP), &cmd_status) != RF_CORE_CMD_OK) { - PRINTF("cc26xx_rf_ble_beacon_process: status=0x%08lx\n", cmd_status); - /* Continue... */ - } - - if(was_on) { - /* We were on, go back to previous primary mode */ - rf_core_primary_mode_restore(); - } else { - /* We were off. Shut back off */ - rf_core_power_down(); - - /* Switch HF clock source to the RCOSC to preserve power */ - oscillators_switch_to_hf_rc(); - } etimer_set(&ble_adv_et, BLE_ADV_DUTY_CYCLE); - interrupts_disabled = ti_lib_int_master_disable(); - - ble_mode_on = RF_BLE_IDLE; - - if(!interrupts_disabled) { - ti_lib_int_master_enable(); - } - /* Wait unless this is the last burst */ if(i < BLE_ADV_MESSAGES - 1) { PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&ble_adv_et)); } } - - interrupts_disabled = ti_lib_int_master_disable(); - - ble_mode_on = RF_BLE_IDLE; - - if(!interrupts_disabled) { - ti_lib_int_master_enable(); - } } PROCESS_END(); } diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/rf-ble.h b/arch/cpu/cc26xx-cc13xx/rf-core/rf-ble.h index 6d91dc13d362e6a9f33f158ad1f74ed8ba431e65..761ca88d6541dbbf4f1ec5a292f14bde8e7e5838 100644 --- a/arch/cpu/cc26xx-cc13xx/rf-core/rf-ble.h +++ b/arch/cpu/cc26xx-cc13xx/rf-core/rf-ble.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2017, University of Bristol - http://www.bristol.ac.uk/ * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,6 +46,7 @@ /*---------------------------------------------------------------------------*/ #include "contiki.h" #include "rf-core/rf-core.h" +#include "radio.h" #include <stdint.h> /*---------------------------------------------------------------------------*/ @@ -57,6 +59,23 @@ #define RF_BLE_IDLE 0 #define RF_BLE_ACTIVE 1 /*---------------------------------------------------------------------------*/ +/* Memory address of BLE MAC address. Can be overwritten by the user by defining BLE_ADDRESS_PTR. */ +#ifndef BLE_ADDRESS_PTR +#define BLE_ADDRESS_PTR (0x500012E8) +#endif +/*---------------------------------------------------------------------------*/ +/* BLE Advertisement channels. Not to be changed by the user. */ +#define BLE_ADV_CHANNEL_MASK 0x07 + +#define BLE_ADV_CHANNEL_37 0x01 +#define BLE_ADV_CHANNEL_38 0x02 +#define BLE_ADV_CHANNEL_39 0x04 + +#define BLE_ADV_CHANNEL_ALL (BLE_ADV_CHANNEL_37 | BLE_ADV_CHANNEL_38 | BLE_ADV_CHANNEL_39) +/*---------------------------------------------------------------------------*/ +/* Maximum BLE advertisement size. Not to be changed by the user. */ +#define BLE_ADV_MAX_SIZE 31 +/*---------------------------------------------------------------------------*/ /** * \brief Set the device name to use with the BLE advertisement/beacon daemon * \param interval The interval (ticks) between two consecutive beacon bursts @@ -89,6 +108,37 @@ void rf_ble_beacond_stop(void); * \retval 0 The BLE daemon is not active, or disabled */ uint8_t rf_ble_is_active(void); + +/** + * \brief Set TX power for BLE advertisements + * \param power The 'at least' TX power in dBm, values avove 5 dBm will be ignored + * + * Set TX power to 'at least' power dBm. + * This works with a lookup table. If the value of 'power' does not exist in + * the lookup table, TXPOWER will be set to the immediately higher available + * value + */ +void rf_ble_set_tx_power(radio_value_t power); + +/** + * \brief Get TX power for BLE advertisements + * \return The TX power for BLE advertisements + */ +radio_value_t rf_ble_get_tx_power(void); + +/** + * \brief Transmit a single BLE advertisement in one or more advertisement channels + * \param channel Bitmask of advertisement channels to be used: use + * BLE_ADV_CHANNEL_37 for channel 37, BLE_ADV_CHANNEL_38 for channel 38, + * BLE_ADV_CHANNEL_39 for channel 39, or any 'or' combination of those + * \param data A pointer to the advertisement data buffer + * \param len The length of the advertisement data. If more than BLE_ADV_MAX_SIZE, + * the first BLE_ADV_MAX_SIZE bytes will be used. + * + * Transmits a given advertisement payload once in one or any arbitrary combination + * of advertisement channels. + */ +void rf_ble_beacon_single(uint8_t channel, uint8_t *data, uint8_t len); /*---------------------------------------------------------------------------*/ #endif /* RF_BLE_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/cc26xx-cc13xx/rtimer-arch.h b/arch/cpu/cc26xx-cc13xx/rtimer-arch.h index 128461c8dccb4e0bdbe0dac4d070b6b7ae67b4bb..c6907ee592a0fd3714956f9099b22643e4173b8d 100644 --- a/arch/cpu/cc26xx-cc13xx/rtimer-arch.h +++ b/arch/cpu/cc26xx-cc13xx/rtimer-arch.h @@ -47,8 +47,6 @@ /*---------------------------------------------------------------------------*/ #include "contiki.h" /*---------------------------------------------------------------------------*/ -#define RTIMER_ARCH_SECOND 65536 -/*---------------------------------------------------------------------------*/ rtimer_clock_t rtimer_arch_now(void); /* HW oscillator frequency is 32 kHz, not 64 kHz and RTIMER_NOW() never returns diff --git a/arch/cpu/cc26xx-cc13xx/slip-arch.c b/arch/cpu/cc26xx-cc13xx/slip-arch.c index 6c6914363aeb4113bdaae613fdafd72189018d7e..f4141e11d0f2528bc6466001c443f6a694ef47cc 100644 --- a/arch/cpu/cc26xx-cc13xx/slip-arch.c +++ b/arch/cpu/cc26xx-cc13xx/slip-arch.c @@ -29,31 +29,16 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** - * \addtogroup cc26xx-char-io - * @{ - * - * \file - * Arch-specific SLIP functions for the CC13xx/CC26xx - */ -/*---------------------------------------------------------------------------*/ #include "contiki.h" #include "dev/cc26xx-uart.h" #include "dev/slip.h" /*---------------------------------------------------------------------------*/ -/** - * \brief Write a byte over SLIP - * \param c the byte - */ void slip_arch_writeb(unsigned char c) { cc26xx_uart_write_byte(c); } /*---------------------------------------------------------------------------*/ -/** - * \brief Initialise the arch-specific SLIP driver - */ void slip_arch_init() { @@ -64,5 +49,3 @@ slip_arch_init() cc26xx_uart_set_input(slip_input_byte); } /*---------------------------------------------------------------------------*/ - -/** @} */ diff --git a/arch/cpu/msp430/Makefile.msp430 b/arch/cpu/msp430/Makefile.msp430 index 6f9e1e29c09dea1ad6c076277887128978c80b5e..841e11285cc02d9efe6353f8e7911e304854e189 100644 --- a/arch/cpu/msp430/Makefile.msp430 +++ b/arch/cpu/msp430/Makefile.msp430 @@ -37,16 +37,9 @@ endif CONTIKI_CPU_DIRS = $(CONTIKI_CPU_FAM_DIR) . dev MSP430 = msp430.c flash.c clock.c leds.c leds-arch.c \ - watchdog.c lpm.c rtimer-arch.c + watchdog.c lpm.c rtimer-arch.c int-master.c UIPDRIVERS = slip.c crc16.c -ifndef CPU_HAS_MSP430X -# include mtarch.c only in the non-large memory model case, because -# the current implementation assumes 16-bit addresses (function pointers -# stored as "unsigned short"). -MSP430 += mtarch.c -endif - CONTIKI_TARGET_SOURCEFILES += $(MSP430) \ $(SYSAPPS) \ $(UIPDRIVERS) @@ -82,7 +75,7 @@ CFLAGSNO = --dlib_config "$(IAR_PATH)/LIB/DLIB/dl430xlfn.h" $(CFLAGSWERROR) # CFLAGSNO = --dlib_config $(IAR_PATH)/LIB/DLIB/dl430xlfn.h -Ohz --multiplier=32 --multiplier_location=4C0 --hw_workaround=CPU40 --core=430X $(CFLAGSWERROR) --data_model large --double=32 endif -LDFLAGSNO += -B -l contiki-$(TARGET).map -s __program_start +LDFLAGSNO += -B -l $(CONTIKI_NG_PROJECT_MAP) -s __program_start # Stack and heap size in hex ifndef IAR_STACK_SIZE IAR_STACK_SIZE=300 @@ -115,11 +108,6 @@ ifeq ($(HOST_OS),Windows) @$(FINALIZE_CYGWIN_DEPENDENCY) endif -CUSTOM_RULE_C_TO_CO = 1 -%.co: %.c - $(TRACE_CC) - $(Q)$(CC) $(CFLAGS) -DAUTOSTART_ENABLE $< -o $@ - AROPTS = -o else @@ -177,7 +165,7 @@ ifndef CFLAGSNO CFLAGSNO = -Wall -mmcu=$(CC_MCU) $(CFLAGSWERROR) endif CFLAGS += -Os -fno-strict-aliasing -LDFLAGS += -mmcu=$(CC_MCU) -Wl,-Map=contiki-$(TARGET).map +LDFLAGS += -mmcu=$(CC_MCU) -Wl,-Map=$(CONTIKI_NG_PROJECT_MAP) ### These flags can reduce the code size and RAM usage with up to 10% SMALL ?= 1 @@ -189,20 +177,22 @@ endif # SMALL endif # IAR +# Define the `_stack` symbol used by the stack check library to be equal to `_end` +LDFLAGS += -Wl,--defsym=_stack=_end + CFLAGS += $(CFLAGSNO) PROJECT_OBJECTFILES += ${addprefix $(OBJECTDIR)/,$(CONTIKI_TARGET_MAIN:.c=.o)} +### CPU-dependent cleanup files +CLEAN += *.firmware *.ihex + ### Compilation rules %-stripped.o: %.c $(CC) $(CFLAGS) -c $< -o $@ $(STRIP) --strip-unneeded -g -x $@ -%.cm: %.co - $(LD) -i -r --unresolved-symbols=ignore-in-object-files -mmsp430x149 -o $@ $^ - $(STRIP) --strip-unneeded -g -x $@ - %-stripped.o: %.o $(STRIP) --strip-unneeded -g -x -o $@ $< @@ -210,7 +200,7 @@ PROJECT_OBJECTFILES += ${addprefix $(OBJECTDIR)/,$(CONTIKI_TARGET_MAIN:.c=.o)} mv $< $@ ifdef IAR -%.ihex: %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a +%.ihex: %.o $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) $(CONTIKI_NG_TARGET_LIB) $(LD) $(LDFLAGSNO) -Fintel-extended $(TARGET_STARTFILES) ${filter-out %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -o $@ else %.ihex: %.$(TARGET) @@ -233,8 +223,8 @@ $(COOJA_PATH)/mspsim/mspsim.jar: $(COOJA_PATH)/mspsim/build.xml %.mspsim: %.${TARGET} ${COOJA_PATH}/mspsim/mspsim.jar java -jar ${COOJA_PATH}/mspsim/mspsim.jar -platform=${TARGET} $< -mspsim-maptable: contiki-${TARGET}.map - java -classpath ${COOJA_PATH}/mspsim/mspsim.jar se.sics.mspsim.util.MapTable $< +%.mspsim-maptable: %.$(TARGET) + java -classpath ${COOJA_PATH}/mspsim/mspsim.jar se.sics.mspsim.util.MapTable $(CONTIKI_NG_PROJECT_MAP) core-labels.o: core.${TARGET} ${CONTIKI}/tools/msp430-make-labels core.${TARGET} > core-labels.S diff --git a/arch/cpu/msp430/cc2420-arch-sfd.c b/arch/cpu/msp430/cc2420-arch-sfd.c index 6ab9a136577f85c424c17dee9c2df9f042870fc3..d1db81ce080fa1eff89b0cff421375e82d942e2e 100644 --- a/arch/cpu/msp430/cc2420-arch-sfd.c +++ b/arch/cpu/msp430/cc2420-arch-sfd.c @@ -29,7 +29,7 @@ */ #include "contiki.h" -#include "dev/spi.h" +#include "dev/spi-legacy.h" #include "cc2420.h" #include "isr_compat.h" diff --git a/arch/cpu/msp430/cc2420-arch.c b/arch/cpu/msp430/cc2420-arch.c index 8a6f0234df764bb83de1ff8ba39ac8fbeb710eb2..c35ce949fda03a935888156db0f4757232355e5a 100644 --- a/arch/cpu/msp430/cc2420-arch.c +++ b/arch/cpu/msp430/cc2420-arch.c @@ -31,7 +31,7 @@ #include "contiki.h" #include "contiki-net.h" -#include "dev/spi.h" +#include "dev/spi-legacy.h" #include "cc2420.h" #include "isr_compat.h" diff --git a/arch/cpu/msp430/cc2520-arch-sfd.c b/arch/cpu/msp430/cc2520-arch-sfd.c index e2671ca58ec5d8f3c7a53245b62ac56f897e8b7f..dc0561f94de0a42899e28b40192e81e69288eabb 100644 --- a/arch/cpu/msp430/cc2520-arch-sfd.c +++ b/arch/cpu/msp430/cc2520-arch-sfd.c @@ -28,7 +28,7 @@ */ #include "contiki.h" -#include "dev/spi.h" +#include "dev/spi-legacy.h" #include "dev/cc2520/cc2520.h" #include "isr_compat.h" diff --git a/arch/cpu/msp430/cc2520-arch.c b/arch/cpu/msp430/cc2520-arch.c index 855f8bc7eec5b7708bd32d7194fa6f535a9e74f7..e63735271a747edc191fb6144cd86b666ca5ba68 100644 --- a/arch/cpu/msp430/cc2520-arch.c +++ b/arch/cpu/msp430/cc2520-arch.c @@ -30,7 +30,7 @@ #include "contiki.h" #include "contiki-net.h" -#include "dev/spi.h" +#include "dev/spi-legacy.h" #include "dev/cc2520/cc2520.h" #include "isr_compat.h" diff --git a/arch/cpu/msp430/dev/uart0-putchar.c b/arch/cpu/msp430/dev/uart0-putchar.c index bf237695b7fe6f696007eff7d36dc182cc10bc06..4c92f9160883b0168b7500e9ca7ba40d98fe2135 100644 --- a/arch/cpu/msp430/dev/uart0-putchar.c +++ b/arch/cpu/msp430/dev/uart0-putchar.c @@ -1,9 +1,39 @@ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" #include "dev/uart0.h" -/* In case of IPv4: putchar() is defined by the SLIP driver */ +#include <string.h> +/*---------------------------------------------------------------------------*/ +#define SLIP_END 0300 +#undef putchar +/*---------------------------------------------------------------------------*/ int putchar(int c) { +#if SLIP_ARCH_CONF_ENABLED + static char debug_frame = 0; + + if(!debug_frame) { /* Start of debug output */ + uart0_writeb(SLIP_END); + uart0_writeb('\r'); /* Type debug line == '\r' */ + debug_frame = 1; + } +#endif /* SLIP_ARCH_CONF_ENABLED */ + + /* Need to also print '\n' because for example COOJA will not show + any output before line end */ uart0_writeb((char)c); + +#if SLIP_ARCH_CONF_ENABLED + /* + * Line buffered output, a newline marks the end of debug output and + * implicitly flushes debug output. + */ + if(c == '\n') { + uart0_writeb(SLIP_END); + debug_frame = 0; + } +#endif /* SLIP_ARCH_CONF_ENABLED */ return c; } +/*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/msp430/dev/uart1-putchar.c b/arch/cpu/msp430/dev/uart1-putchar.c index 7623b435ac6df52300a2f9b78553a68a6c2af71d..14146d9dccd9bc37aafa105444efb2400f72a1d5 100644 --- a/arch/cpu/msp430/dev/uart1-putchar.c +++ b/arch/cpu/msp430/dev/uart1-putchar.c @@ -1,9 +1,39 @@ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" #include "dev/uart1.h" -/* In case of IPv4: putchar() is defined by the SLIP driver */ +#include <string.h> +/*---------------------------------------------------------------------------*/ +#define SLIP_END 0300 +#undef putchar +/*---------------------------------------------------------------------------*/ int putchar(int c) { +#if SLIP_ARCH_CONF_ENABLED + static char debug_frame = 0; + + if(!debug_frame) { /* Start of debug output */ + uart1_writeb(SLIP_END); + uart1_writeb('\r'); /* Type debug line == '\r' */ + debug_frame = 1; + } +#endif /* SLIP_ARCH_CONF_ENABLED */ + + /* Need to also print '\n' because for example COOJA will not show + any output before line end */ uart1_writeb((char)c); + +#if SLIP_ARCH_CONF_ENABLED + /* + * Line buffered output, a newline marks the end of debug output and + * implicitly flushes debug output. + */ + if(c == '\n') { + uart1_writeb(SLIP_END); + debug_frame = 0; + } +#endif /* SLIP_ARCH_CONF_ENABLED */ return c; } +/*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/msp430/f1xxx/spi.c b/arch/cpu/msp430/f1xxx/spi-legacy.c similarity index 87% rename from arch/cpu/msp430/f1xxx/spi.c rename to arch/cpu/msp430/f1xxx/spi-legacy.c index c9e98508f21255dc0d24bfb1cb6a98d06ad69c0d..38adfaa31a6eb7fd71cd2e2de768fd5738ca84c6 100644 --- a/arch/cpu/msp430/f1xxx/spi.c +++ b/arch/cpu/msp430/f1xxx/spi-legacy.c @@ -1,30 +1,30 @@ /* * Copyright (c) 2006, Swedish Institute of Computer Science - * All rights reserved. + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. * */ @@ -35,7 +35,7 @@ * exclusive. Set spi_busy so that interrupt handlers can check if * they are allowed to use the bus or not. Only the CC2420 radio needs * this in practice. - * + * */ unsigned char spi_busy = 0; diff --git a/arch/cpu/msp430/f2xxx/spi.c b/arch/cpu/msp430/f2xxx/spi-legacy.c similarity index 100% rename from arch/cpu/msp430/f2xxx/spi.c rename to arch/cpu/msp430/f2xxx/spi-legacy.c diff --git a/arch/cpu/msp430/f5xxx/spi.c b/arch/cpu/msp430/f5xxx/spi-legacy.c similarity index 100% rename from arch/cpu/msp430/f5xxx/spi.c rename to arch/cpu/msp430/f5xxx/spi-legacy.c diff --git a/arch/cpu/msp430/int-master.c b/arch/cpu/msp430/int-master.c new file mode 100644 index 0000000000000000000000000000000000000000..5e50a563c9545a9a4cee1847486fcc245bef20a7 --- /dev/null +++ b/arch/cpu/msp430/int-master.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \file + * Master interrupt manipulation implementation for the MSP430 + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "sys/int-master.h" + +#include <stdbool.h> +/*---------------------------------------------------------------------------*/ +void +int_master_enable(void) +{ + eint(); +} +/*---------------------------------------------------------------------------*/ +int_master_status_t +int_master_read_and_disable(void) +{ + __istate_t status = __get_interrupt_state(); + dint(); + return status; +} +/*---------------------------------------------------------------------------*/ +void +int_master_status_set(int_master_status_t status) +{ + __set_interrupt_state(status); +} +/*---------------------------------------------------------------------------*/ +bool +int_master_is_enabled(void) +{ + return __get_interrupt_state() & GIE ? true : false; +} +/*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/msp430/leds-arch.c b/arch/cpu/msp430/leds-arch.c index fe63d8ae4b95099c6f33d970177b19d4b7fed2c3..c8131ee3eb5cc5ae3ca8f7522a08c3f709edf000 100644 --- a/arch/cpu/msp430/leds-arch.c +++ b/arch/cpu/msp430/leds-arch.c @@ -46,10 +46,10 @@ leds_arch_init(void) LEDS_PxOUT |= (LEDS_CONF_RED | LEDS_CONF_GREEN | LEDS_CONF_YELLOW); } /*---------------------------------------------------------------------------*/ -unsigned char +leds_mask_t leds_arch_get(void) { - unsigned char leds; + leds_mask_t leds; leds = LEDS_PxOUT; return ((leds & LEDS_CONF_RED) ? 0 : LEDS_RED) | ((leds & LEDS_CONF_GREEN) ? 0 : LEDS_GREEN) @@ -57,7 +57,7 @@ leds_arch_get(void) } /*---------------------------------------------------------------------------*/ void -leds_arch_set(unsigned char leds) +leds_arch_set(leds_mask_t leds) { LEDS_PxOUT = (LEDS_PxOUT & ~(LEDS_CONF_RED|LEDS_CONF_GREEN|LEDS_CONF_YELLOW)) | ((leds & LEDS_RED) ? 0 : LEDS_CONF_RED) diff --git a/arch/cpu/nrf52832/putchar.c b/arch/cpu/msp430/msp430-conf.h similarity index 72% rename from arch/cpu/nrf52832/putchar.c rename to arch/cpu/msp430/msp430-conf.h index c4163ba3d6cedcbeb2d216fdfdcefc435681e11d..f4f0da54cc9a53947adb0796aa9a98867e1373a5 100644 --- a/arch/cpu/nrf52832/putchar.c +++ b/arch/cpu/msp430/msp430-conf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Nordic Semiconductor + * Copyright (c) 2007, Swedish Institute of Computer Science * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,46 +25,37 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ -/** - * \addtogroup nrf52832 - * @{ - * - * \file - * Hardware specific implementation of putchar() and puts() functions. - * \author - * Wojciech Bober <wojciech.bober@nordicsemi.no> - * - */ -/*---------------------------------------------------------------------------*/ -#include <string.h> -#include "dev/uart0.h" /*---------------------------------------------------------------------------*/ -int -putchar(int c) -{ - uart0_writeb(c); - return c; -} +#ifndef MSP430_CONF_H_ +#define MSP430_CONF_H_ /*---------------------------------------------------------------------------*/ -int -puts(const char *str) -{ - int i; +/* default DCOSYNCH Period is 30 seconds */ +#ifdef DCOSYNCH_CONF_PERIOD +#define DCOSYNCH_PERIOD DCOSYNCH_CONF_PERIOD +#else +#define DCOSYNCH_PERIOD 30 +#endif - if (str == NULL) { - return 0; - } +#ifdef F_CPU +#define MSP430_CPU_SPEED F_CPU +#else +#define MSP430_CPU_SPEED 2457600UL +#endif - for (i = 0; i < strlen(str); i++) { - uart0_writeb(str[i]); - } +#ifndef SLIP_ARCH_CONF_ENABLED +/* + * Determine whether we need SLIP + * This will keep working while UIP_FALLBACK_INTERFACE and CMD_CONF_OUTPUT + * keep using SLIP + */ +#if defined(UIP_FALLBACK_INTERFACE) || defined(CMD_CONF_OUTPUT) +#define SLIP_ARCH_CONF_ENABLED 1 +#else +#define SLIP_ARCH_CONF_ENABLED 0 +#endif +#endif - uart0_writeb('\n'); - return i; -} /*---------------------------------------------------------------------------*/ -/** - * @} - */ +#endif /* MSP430_CONF_H_ */ +/*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/msp430/msp430def.h b/arch/cpu/msp430/msp430-def.h similarity index 73% rename from arch/cpu/msp430/msp430def.h rename to arch/cpu/msp430/msp430-def.h index 05e9b0bbce11fd682702f185bec15b9bde460ded..e032bb4a064f913aa967591a53286b97dbbe89f0 100644 --- a/arch/cpu/msp430/msp430def.h +++ b/arch/cpu/msp430/msp430-def.h @@ -1,34 +1,34 @@ /* * Copyright (c) 2007, Swedish Institute of Computer Science - * All rights reserved. + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ -#ifndef MSP430DEF_H -#define MSP430DEF_H +#ifndef MSP430_DEF_H_ +#define MSP430_DEF_H_ #ifdef __IAR_SYSTEMS_ICC__ #include <intrinsics.h> @@ -56,22 +56,14 @@ #endif /* __IAR_SYSTEMS_ICC__ */ +/* Master interrupt state representation data type */ +#define INT_MASTER_CONF_STATUS_DATATYPE __istate_t + #ifndef BV #define BV(x) (1 << x) #endif -#ifdef HAVE_STDINT_H #include <stdint.h> -#else -#ifndef uint8_t -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned long uint32_t; -typedef signed char int8_t; -typedef short int16_t; -typedef long int32_t; -#endif -#endif /* !HAVE_STDINT_H */ /* These names are deprecated, use C99 names. */ typedef uint8_t u8_t; @@ -79,23 +71,15 @@ typedef uint16_t u16_t; typedef uint32_t u32_t; typedef int32_t s32_t; -/* default DCOSYNCH Period is 30 seconds */ -#ifdef DCOSYNCH_CONF_PERIOD -#define DCOSYNCH_PERIOD DCOSYNCH_CONF_PERIOD -#else -#define DCOSYNCH_PERIOD 30 -#endif - -void msp430_cpu_init(void); /* Rename to cpu_init() later! */ -void msp430_sync_dco(void); - - -#define cpu_init() msp430_cpu_init() +/* Types for clocks and uip_stats */ +typedef unsigned short uip_stats_t; +typedef unsigned long clock_time_t; +typedef long off_t; -void *sbrk(int); +/* Our clock resolution, this is the same as Unix HZ. */ +#define CLOCK_CONF_SECOND 128UL typedef int spl_t; -/* void splx_(spl_t); */ spl_t splhigh_(void); #define splhigh() splhigh_() @@ -119,21 +103,23 @@ void *w_memset(void *out, int value, size_t n); #endif /* memcpy */ #endif /* __GNUC__ && __MSP430__ && MSP430_MEMCPY_WORKAROUND */ - -/* Moved from the msp430.h file with other msp430 related defines */ - -#ifdef F_CPU -#define MSP430_CPU_SPEED F_CPU -#else -#define MSP430_CPU_SPEED 2457600UL -#endif +#define memory_barrier() asm volatile("" : : : "memory") #define MSP430_REQUIRE_CPUON 0 #define MSP430_REQUIRE_LPM1 1 #define MSP430_REQUIRE_LPM2 2 #define MSP430_REQUIRE_LPM3 3 +/* Platform-specific checksum implementation */ +#define UIP_ARCH_IPCHKSUM 1 + +#define BAUD2UBR(baud) ((F_CPU/baud)) + void msp430_add_lpm_req(int req); void msp430_remove_lpm_req(int req); +void msp430_cpu_init(void); /* Rename to cpu_init() later! */ +void msp430_sync_dco(void); +#define cpu_init() msp430_cpu_init() +void *sbrk(int); -#endif /* MSP430DEF_H */ +#endif /* MSP430_DEF_H_ */ diff --git a/arch/cpu/msp430/mtarch.c b/arch/cpu/msp430/mtarch.c deleted file mode 100644 index 0ecd5d9c0278ddcb9c3beb31d76d16e4ed30b59d..0000000000000000000000000000000000000000 --- a/arch/cpu/msp430/mtarch.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2005, Swedish Institute of Computer Science - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ - -#include <stdio.h> -#include "sys/mt.h" - -#ifdef __IAR_SYSTEMS_ICC__ -#define __asm__ asm -#endif - -static unsigned short *sptmp; -static struct mtarch_thread *running; - -/*--------------------------------------------------------------------------*/ -void -mtarch_init(void) -{ - -} -/*--------------------------------------------------------------------------*/ -static void -mtarch_wrapper(void) -{ - /* Call thread function with argument */ - ((void (*)(void *))running->function)((void*)running->data); -} -/*--------------------------------------------------------------------------*/ -void -mtarch_start(struct mtarch_thread *t, - void (*function)(void *), void *data) -{ - int i; - - for(i = 0; i < MTARCH_STACKSIZE; ++i) { - t->stack[i] = i; - } - - t->sp = &t->stack[MTARCH_STACKSIZE - 1]; - - *t->sp = (unsigned short)mt_exit; - --t->sp; - - *t->sp = (unsigned short)mtarch_wrapper; - --t->sp; - - /* Space for registers. */ - t->sp -= 11; - - /* Store function and argument (used in mtarch_wrapper) */ - t->data = data; - t->function = function; -} -/*--------------------------------------------------------------------------*/ - -static void -sw(void) -{ - - sptmp = running->sp; - - __asm__("push r4"); - __asm__("push r5"); - __asm__("push r6"); - __asm__("push r7"); - __asm__("push r8"); - __asm__("push r9"); - __asm__("push r10"); - __asm__("push r11"); - __asm__("push r12"); - __asm__("push r13"); - __asm__("push r14"); - __asm__("push r15"); - -#ifdef __IAR_SYSTEMS_ICC__ -/* use IAR intrinsic functions */ - running->sp = (unsigned short *) __get_SP_register(); - __set_SP_register((unsigned short) sptmp); -#else - __asm__("mov.w r1,%0" : "=r" (running->sp)); - __asm__("mov.w %0,r1" : : "m" (sptmp)); -#endif - - __asm__("pop r15"); - __asm__("pop r14"); - __asm__("pop r13"); - __asm__("pop r12"); - __asm__("pop r11"); - __asm__("pop r10"); - __asm__("pop r9"); - __asm__("pop r8"); - __asm__("pop r7"); - __asm__("pop r6"); - __asm__("pop r5"); - __asm__("pop r4"); -} -/*--------------------------------------------------------------------------*/ -void -mtarch_exec(struct mtarch_thread *t) -{ - running = t; - sw(); - running = NULL; -} -/*--------------------------------------------------------------------------*/ -void -mtarch_remove(void) -{ - -} -/*--------------------------------------------------------------------------*/ -void -mtarch_yield(void) -{ - sw(); -} -/*--------------------------------------------------------------------------*/ -void -mtarch_pstop(void) -{ - -} -/*--------------------------------------------------------------------------*/ -void -mtarch_pstart(void) -{ - -} -/*--------------------------------------------------------------------------*/ -void -mtarch_stop(struct mtarch_thread *thread) -{ - -} -/*--------------------------------------------------------------------------*/ -int -mtarch_stack_usage(struct mt_thread *t) -{ - int i; - - for(i = 0; i < MTARCH_STACKSIZE; ++i) { - if(t->thread.stack[i] != (unsigned short)i) { - return MTARCH_STACKSIZE - i; - } - } - - return MTARCH_STACKSIZE; -} -/*--------------------------------------------------------------------------*/ diff --git a/arch/cpu/native/Makefile.native b/arch/cpu/native/Makefile.native index ba473a3d3942569b11be83c2bf9bcc076e1735e3..af7328b3176fb7a8d323b2ec8aa2c8f16794715a 100644 --- a/arch/cpu/native/Makefile.native +++ b/arch/cpu/native/Makefile.native @@ -1,6 +1,7 @@ CONTIKI_CPU_DIRS = . net dev -CONTIKI_SOURCEFILES += mtarch.c rtimer-arch.c watchdog.c eeprom.c +CONTIKI_SOURCEFILES += rtimer-arch.c watchdog.c eeprom.c int-master.c +CONTIKI_SOURCEFILES += gpio-hal-arch.c ### Compiler definitions CC ?= gcc @@ -20,12 +21,12 @@ CFLAGSNO = -Wall -g -I/usr/local/include $(CFLAGSWERROR) CFLAGS += $(CFLAGSNO) ifeq ($(HOST_OS),Darwin) -AROPTS = -r -LDFLAGS += -Wl,-flat_namespace +AROPTS = -rc +LDFLAGS += -Wl,-flat_namespace,-map,$(CONTIKI_NG_PROJECT_MAP) CFLAGS += -DHAVE_SNPRINTF=1 -U__ASSERT_USE_STDERR else ifeq ($(HOST_OS),Linux) -LDFLAGS += -Wl,-Map=contiki-$(TARGET).map,-export-dynamic +LDFLAGS += -Wl,-Map=$(CONTIKI_NG_PROJECT_MAP),-export-dynamic endif endif diff --git a/arch/cpu/native/dev/gpio-hal-arch.c b/arch/cpu/native/dev/gpio-hal-arch.c new file mode 100644 index 0000000000000000000000000000000000000000..553a23444d744c6a56d13fd18fc2f75a34e84e6f --- /dev/null +++ b/arch/cpu/native/dev/gpio-hal-arch.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +#include "sys/log.h" + +#include <stdint.h> +/*---------------------------------------------------------------------------*/ +/* Log configuration */ +#define LOG_MODULE "GPIO arch" +#define LOG_LEVEL LOG_LEVEL_NONE +/*---------------------------------------------------------------------------*/ +static gpio_hal_pin_cfg_t pin_cfg[GPIO_HAL_PIN_COUNT]; +static uint8_t pin_state[GPIO_HAL_PIN_COUNT]; +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_interrupt_enable(gpio_hal_pin_t pin) +{ + if(pin >= GPIO_HAL_PIN_COUNT) { + LOG_ERR("Pin %u out of bounds\n", pin); + return; + } + + LOG_DBG("Pin %u: Enabled interrupt\n", pin); +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_interrupt_disable(gpio_hal_pin_t pin) +{ + if(pin >= GPIO_HAL_PIN_COUNT) { + LOG_ERR("Pin %u out of bounds\n", pin); + return; + } + + LOG_DBG("Pin %u: Disabled interrupt\n", pin); +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg) +{ + if(pin >= GPIO_HAL_PIN_COUNT) { + LOG_ERR("Pin %u out of bounds\n", pin); + return; + } + + pin_cfg[pin] = cfg; + LOG_DBG("Pin %u: Set config=0x%02x\n", pin, pin_cfg[pin]); +} +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_cfg_t +gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin) +{ + if(pin >= GPIO_HAL_PIN_COUNT) { + LOG_ERR("Pin %u out of bounds\n", pin); + return 0; + } + + LOG_DBG("Pin %u: Config=0x%02x\n", pin, pin_cfg[pin]); + return pin_cfg[pin]; +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_pin_set_input(gpio_hal_pin_t pin) +{ + if(pin >= GPIO_HAL_PIN_COUNT) { + LOG_ERR("Pin %u out of bounds\n", pin); + return; + } + + LOG_DBG("Pin %u: Set input\n", pin); +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_pin_set_output(gpio_hal_pin_t pin) +{ + if(pin >= GPIO_HAL_PIN_COUNT) { + LOG_ERR("Pin %u out of bounds\n", pin); + return; + } + + LOG_DBG("Pin %u: Set output\n", pin); +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_set_pin(gpio_hal_pin_t pin) +{ + if(pin >= GPIO_HAL_PIN_COUNT) { + LOG_ERR("Pin %u out of bounds\n", pin); + return; + } + + pin_state[pin] = 1; + LOG_DBG("Pin %u: Set\n", pin); +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_clear_pin(gpio_hal_pin_t pin) +{ + if(pin >= GPIO_HAL_PIN_COUNT) { + LOG_ERR("Pin %u out of bounds\n", pin); + return; + } + + pin_state[pin] = 0; + LOG_DBG("Pin %u: Clear\n", pin); +} +/*---------------------------------------------------------------------------*/ +uint8_t +gpio_hal_arch_read_pin(gpio_hal_pin_t pin) +{ + if(pin >= GPIO_HAL_PIN_COUNT) { + LOG_ERR("Pin %u out of bounds\n", pin); + return 0; + } + + LOG_DBG("Pin %u: Read=%u\n", pin, pin_state[pin]); + return pin_state[pin]; +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_write_pin(gpio_hal_pin_t pin, uint8_t value) +{ + if(pin >= GPIO_HAL_PIN_COUNT) { + LOG_ERR("Pin %u out of bounds\n", pin); + return; + } + + pin_state[pin] = value; + LOG_DBG("Pin %u: Write=%u\n", pin, pin_state[pin]); +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_set_pins(gpio_hal_pin_mask_t pins) +{ + gpio_hal_pin_t pin; + + for(pin = 0; pin < GPIO_HAL_PIN_COUNT; pin++) { + if(pins & (1 << pin)) { + pin_state[pin] = 1; + } + } + + LOG_DBG("Set pins 0x%08" PRIx32 "\n", pins); +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_clear_pins(gpio_hal_pin_mask_t pins) +{ + gpio_hal_pin_t pin; + + for(pin = 0; pin < GPIO_HAL_PIN_COUNT; pin++) { + if(pins & (1 << pin)) { + pin_state[pin] = 0; + } + } + + LOG_DBG("Clear pins 0x%08" PRIx32 "\n", pins); +} +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_mask_t +gpio_hal_arch_read_pins(gpio_hal_pin_mask_t pins) +{ + gpio_hal_pin_t pin; + gpio_hal_pin_mask_t state = 0; + + for(pin = 0; pin < GPIO_HAL_PIN_COUNT; pin++) { + state |= (pin_state[pin] << pin); + } + + LOG_DBG("Read pins 0x%08" PRIx32 "\n", state); + return state; +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_write_pins(gpio_hal_pin_mask_t pins, gpio_hal_pin_mask_t value) +{ + gpio_hal_pin_t pin; + + for(pin = 0; pin < GPIO_HAL_PIN_COUNT; pin++) { + if(pins & (1 << pin)) { + pin_state[pin] = (value & (1 << pin)) == 0 ? 0 : 1; + } + } + + LOG_DBG("Write pins 0x%08" PRIx32 "->0x%08" PRIx32 "\n", pins, value); +} +/*---------------------------------------------------------------------------*/ diff --git a/arch/platform/srf06-cc26xx/launchpad/button-sensor.h b/arch/cpu/native/int-master.c similarity index 74% rename from arch/platform/srf06-cc26xx/launchpad/button-sensor.h rename to arch/cpu/native/int-master.c index 0c945d3f7f5103c081864ad2897daaeaa7d1c927..177dbd4424c30967c00ee069a728791de85d161f 100644 --- a/arch/platform/srf06-cc26xx/launchpad/button-sensor.h +++ b/arch/cpu/native/int-master.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright @@ -28,38 +29,39 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** - * \addtogroup launchpad-peripherals - * @{ - * - * \defgroup launchpad-button-sensor LaunchPad Button Driver - * - * One of the buttons can be configured as general purpose or as an on/off key - * @{ - * - * \file - * Header file for the LaunchPad Button Driver - */ +#include "contiki.h" +#include "sys/int-master.h" + +#include <stdbool.h> /*---------------------------------------------------------------------------*/ -#ifndef BUTTON_SENSOR_H_ -#define BUTTON_SENSOR_H_ +#define DISABLED 0 +#define ENABLED 1 /*---------------------------------------------------------------------------*/ -#include "lib/sensors.h" +static int_master_status_t stat = DISABLED; /*---------------------------------------------------------------------------*/ -#define BUTTON_SENSOR "Button" +void +int_master_enable(void) +{ + stat = ENABLED; +} /*---------------------------------------------------------------------------*/ -#define BUTTON_SENSOR_VALUE_STATE 0 -#define BUTTON_SENSOR_VALUE_DURATION 1 - -#define BUTTON_SENSOR_VALUE_RELEASED 0 -#define BUTTON_SENSOR_VALUE_PRESSED 1 +int_master_status_t +int_master_read_and_disable(void) +{ + int_master_status_t rv = stat; + stat = DISABLED; + return rv; +} /*---------------------------------------------------------------------------*/ -extern const struct sensors_sensor button_left_sensor; -extern const struct sensors_sensor button_right_sensor; +void +int_master_status_set(int_master_status_t status) +{ + stat = status; +} /*---------------------------------------------------------------------------*/ -#endif /* BUTTON_SENSOR_H_ */ +bool +int_master_is_enabled(void) +{ + return stat == DISABLED ? false : true; +} /*---------------------------------------------------------------------------*/ -/** - * @} - * @} - */ diff --git a/arch/cpu/native/mtarch.c b/arch/cpu/native/mtarch.c deleted file mode 100644 index 397891efbbd389796b7d8c241138994046b6a25a..0000000000000000000000000000000000000000 --- a/arch/cpu/native/mtarch.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2007, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - * Author: Oliver Schmidt <ol.sc@web.de> - * - * - */ - -#include "sys/mt.h" - -#ifndef MTARCH_STACKSIZE -#define MTARCH_STACKSIZE 4096 -#endif /* MTARCH_STACKSIZE */ - -#if defined(_WIN32) || defined(__CYGWIN__) - -#define WIN32_LEAN_AND_MEAN -#include <windows.h> - -static void *main_fiber; - -#elif defined(__linux) - -#include <stdlib.h> -#include <signal.h> -#include <ucontext.h> - -struct mtarch_t { - char stack[MTARCH_STACKSIZE]; - ucontext_t context; -}; - -static ucontext_t main_context; -static ucontext_t *running_context; -#elif defined(__APPLE) -/* No support for OS-X at the moment as swapcontext, etc are deprecated */ - -#endif /* _WIN32 || __CYGWIN__ || __linux */ - -/*--------------------------------------------------------------------------*/ -void -mtarch_init(void) -{ -#if defined(_WIN32) || defined(__CYGWIN__) - - main_fiber = ConvertThreadToFiber(NULL); - -#endif /* _WIN32 || __CYGWIN__ */ -} -/*--------------------------------------------------------------------------*/ -void -mtarch_remove(void) -{ -#if defined(_WIN32) || defined(__CYGWIN__) - - ConvertFiberToThread(); - -#endif /* _WIN32 || __CYGWIN__ */ -} -/*--------------------------------------------------------------------------*/ -void -mtarch_start(struct mtarch_thread *thread, - void (* function)(void *data), - void *data) -{ -#if defined(_WIN32) || defined(__CYGWIN__) - - thread->mt_thread = CreateFiber(0, (LPFIBER_START_ROUTINE)function, data); - -#elif defined(__linux) - - thread->mt_thread = malloc(sizeof(struct mtarch_t)); - - getcontext(&((struct mtarch_t *)thread->mt_thread)->context); - - ((struct mtarch_t *)thread->mt_thread)->context.uc_link = NULL; - ((struct mtarch_t *)thread->mt_thread)->context.uc_stack.ss_sp = - ((struct mtarch_t *)thread->mt_thread)->stack; - ((struct mtarch_t *)thread->mt_thread)->context.uc_stack.ss_size = - sizeof(((struct mtarch_t *)thread->mt_thread)->stack); - - /* Some notes: - - If a CPU needs stronger alignment for the stack than malloc() - guarantees (like i.e. IA64) then makecontext() is supposed to - add that alignment internally. - - According to POSIX the arguments to function() are of type int - and there are in fact 64-bit implementations which support only - 32 bits per argument meaning that a pointer argument has to be - splitted into two arguments. - - Most implementations interpret context.uc_stack.ss_sp on entry - as the lowest stack address even if the CPU stack actually grows - downwards. Although this means that ss_sp does NOT represent the - CPU stack pointer this behaviour makes perfectly sense as it is - the only way to stay independent from the CPU architecture. But - Solaris prior to release 10 interprets ss_sp as highest stack - address thus requiring special handling. */ - makecontext(&((struct mtarch_t *)thread->mt_thread)->context, - (void (*)(void))function, 1, data); - -#endif /* _WIN32 || __CYGWIN__ || __linux */ -} -/*--------------------------------------------------------------------------*/ -void -mtarch_yield(void) -{ -#if defined(_WIN32) || defined(__CYGWIN__) - - SwitchToFiber(main_fiber); - -#elif defined(__linux) - - swapcontext(running_context, &main_context); - -#endif /* _WIN32 || __CYGWIN__ || __linux */ -} -/*--------------------------------------------------------------------------*/ -void -mtarch_exec(struct mtarch_thread *thread) -{ -#if defined(_WIN32) || defined(__CYGWIN__) - - SwitchToFiber(thread->mt_thread); - -#elif defined(__linux) - running_context = &((struct mtarch_t *)thread->mt_thread)->context; - swapcontext(&main_context, running_context); - running_context = NULL; - -#endif /* _WIN32 || __CYGWIN__ || __linux */ -} -/*--------------------------------------------------------------------------*/ -void -mtarch_stop(struct mtarch_thread *thread) -{ -#if defined(_WIN32) || defined(__CYGWIN__) - - DeleteFiber(thread->mt_thread); - -#elif defined(linux) || defined(__linux) - free(thread->mt_thread); - -#endif /* _WIN32 || __CYGWIN__ || __linux */ -} -/*--------------------------------------------------------------------------*/ -void -mtarch_pstart(void) -{ -} -/*--------------------------------------------------------------------------*/ -void -mtarch_pstop(void) -{ -} -/*--------------------------------------------------------------------------*/ diff --git a/arch/cpu/native/mtarch.h b/arch/cpu/native/mtarch.h deleted file mode 100644 index d006c1360d602a44eef9eb63030ecac9b02eac97..0000000000000000000000000000000000000000 --- a/arch/cpu/native/mtarch.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2007, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - * Author: Oliver Schmidt <ol.sc@web.de> - * - */ - -#ifndef MTARCH_H_ -#define MTARCH_H_ - -struct mtarch_thread { - void *mt_thread; -}; - -#endif /* MTARCH_H_ */ diff --git a/examples/rpl-border-router/embedded/sky/target-conf.h b/arch/cpu/native/native-def.h similarity index 90% rename from examples/rpl-border-router/embedded/sky/target-conf.h rename to arch/cpu/native/native-def.h index 3b0b0fcd4dda89a1bde80e52c15e8be9595ae2e6..d85ae7100440cf0ec9451ca1506d1e7db7e2e853 100644 --- a/examples/rpl-border-router/embedded/sky/target-conf.h +++ b/arch/cpu/native/native-def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,11 +29,10 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -#ifndef TARGET_CONF_H_ -#define TARGET_CONF_H_ +#ifndef NATIVE_DEF_H_ +#define NATIVE_DEF_H_ /*---------------------------------------------------------------------------*/ -#define QUEUEBUF_CONF_NUM 4 -#define UIP_CONF_BUFFER_SIZE 140 +#define GPIO_HAL_CONF_ARCH_SW_TOGGLE 1 /*---------------------------------------------------------------------------*/ -#endif /* TARGET_CONF_H_ */ +#endif /* NATIVE_DEF_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/native/rtimer-arch.c b/arch/cpu/native/rtimer-arch.c index 2dab7efb62987ec076902473bb5e38ea95c26ff3..ad081c9f51a5818cbc905ee52f15cd59acfe4afc 100644 --- a/arch/cpu/native/rtimer-arch.c +++ b/arch/cpu/native/rtimer-arch.c @@ -79,11 +79,11 @@ rtimer_arch_schedule(rtimer_clock_t t) c = t - (unsigned short)clock_time(); - val.it_value.tv_sec = c / 1000; - val.it_value.tv_usec = (c % 1000) * 1000; + val.it_value.tv_sec = c / CLOCK_SECOND; + val.it_value.tv_usec = (c % CLOCK_SECOND) * CLOCK_SECOND; - PRINTF("rtimer_arch_schedule time %u %u in %d.%d seconds\n", t, c, c / 1000, - (c % 1000) * 1000); + PRINTF("rtimer_arch_schedule time %u %u in %d.%d seconds\n", t, c, val.it_value.tv_sec, + val.it_value.tv_usec); val.it_interval.tv_sec = val.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &val, NULL); diff --git a/arch/cpu/nrf52832/Makefile.nrf52832 b/arch/cpu/nrf52832/Makefile.nrf52832 index f6752ef8c0b3f9bf4bcd45ddafae1eadb2a3bb3c..3765484d864edb2eb6dac08226af2619709ad7fa 100644 --- a/arch/cpu/nrf52832/Makefile.nrf52832 +++ b/arch/cpu/nrf52832/Makefile.nrf52832 @@ -14,12 +14,6 @@ endif # custom MAC: ble_ipsp_mac_driver MAKE_MAC ?= MAKE_MAC_OTHER -# we only support IPv6 -MAKE_NET ?= MAKE_NET_IPV6 -ifneq ($(MAKE_NET),MAKE_NET_IPV6) - $(error Only IPv6 stack is supported!) -endif - $(info SDK: $(NRF52_SDK_ROOT)) ifeq ($(NRF52_DK_REVISION),) @@ -46,19 +40,6 @@ OBJECT_DIRECTORY = $(OBJECTDIR) LISTING_DIRECTORY := $(OBJECTDIR) OUTPUT_BINARY_DIRECTORY := bin_$(TARGET) -MK := mkdir -RM := rm -rf - -# Toolchain commands -CC := arm-none-eabi-gcc -AS := arm-none-eabi-as -AR := arm-none-eabi-ar -LD := arm-none-eabi-ld -NM := arm-none-eabi-nm -OBJDUMP := arm-none-eabi-objdump -OBJCOPY := arm-none-eabi-objcopy -SIZE := arm-none-eabi-size - # JLink JLINK := $(NRF52_JLINK_PATH)/JLinkExe JLINK_OPTS = -Device NRF52 -if swd -speed 1000 @@ -73,7 +54,8 @@ remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-ou CONTIKI_CPU_DIRS += . dev ble #compat ### CPU-dependent source files -CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c uart0.c putchar.c watchdog.c +CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c uart0.c dbg.c watchdog.c +CONTIKI_CPU_SOURCEFILES += int-master.c ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1) CONTIKI_CPU_SOURCEFILES += ble-core.c ble-mac.c @@ -141,44 +123,24 @@ EXTERNALDIRS += $(addprefix $(NRF52_SDK_ROOT)/, $(INC_PATHS)) # Sorting removes duplicates BUILD_DIRECTORIES := $(sort $(OUTPUT_BINARY_DIRECTORY) $(LISTING_DIRECTORY)) -# Clean files and directories -CLEAN += bin_$(TARGET) lst_$(TARGET) nrf52832.a *.elf *.hex - #flags common to all targets ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1) CFLAGS += -DSOFTDEVICE_PRESENT CFLAGS += -DS132 endif -SMALL ?= 1 -ifeq ($(SMALL),1) -CFLAGS += -Os -else -CFLAGS += -O2 -endif - CFLAGS += -DNRF52 CFLAGS += -DBOARD_$(shell echo $(NRF52_DK_REVISION) | tr a-z A-Z) CFLAGS += -D__HEAP_SIZE=512 CFLAGS += -DSWI_DISABLE0 CFLAGS += -DCONFIG_GPIO_AS_PINRESET CFLAGS += -DBLE_STACK_SUPPORT_REQD -CFLAGS += -mcpu=cortex-m4 -CFLAGS += -mthumb -mabi=aapcs --std=gnu99 -CFLAGS += -Wall -ifeq ($(WERROR),1) -CFLAGS += -Werror -endif CFLAGS += -ggdb CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 -# keep every function in separate section. This will allow linker to dump unused functions -CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing -CFLAGS += -fno-builtin --short-enums # keep every function in separate section. This will allow linker to dump unused functions -LDFLAGS += -Xlinker -Map=$(LISTING_DIRECTORY)/$(OUTPUT_FILENAME).map -LDFLAGS += -mthumb -mabi=aapcs -L $(TEMPLATE_PATH) -T$(LINKER_SCRIPT) -LDFLAGS += -mcpu=cortex-m4 +LDFLAGS += -Xlinker -Map=$(CONTIKI_NG_PROJECT_MAP) +LDFLAGS += -mabi=aapcs -L $(TEMPLATE_PATH) -T$(LINKER_SCRIPT) LDFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 # let linker to dump unused sections LDFLAGS += -Wl,--gc-sections @@ -210,43 +172,19 @@ vpath %.s $(ASM_PATHS) OBJECTS = $(C_OBJECTS) $(ASM_OBJECTS) -TARGET_LIBS= nrf52832.a $(NRF52_SDK_ROOT)/components/iot/ble_6lowpan/lib/ble_6lowpan.a +CLEAN += nrf52832.a -### Don't treat the .elf as intermediate -.PRECIOUS: %.hex %.bin +TARGET_LIBS= nrf52832.a $(NRF52_SDK_ROOT)/components/iot/ble_6lowpan/lib/ble_6lowpan.a nrf52832.a: $(OBJECTS) $(TRACE_AR) $(Q)$(AR) $(AROPTS) $@ $^ -### Compilation rules -CUSTOM_RULE_LINK=1 - -%.elf: $(TARGET_STARTFILES) %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(TARGET_LIBS) - $(TRACE_LD) - $(Q)$(CC) $(LDFLAGS) ${filter %o %.co %.a,$^} -o $@ - # Assemble files $(OBJECT_DIRECTORY)/%.o: %.s - @echo Compiling file: $(notdir $<) + $(TRACE_CC) $(Q)$(CC) $(ASMFLAGS) $(addprefix -I$(NRF52_SDK_ROOT)/, $(INC_PATHS)) -c -o $@ $< -# Create binary file from the .out file -%.bin: %.elf - @echo Preparing: $@ - $(Q)$(OBJCOPY) -O binary $^ $@ - -# Create binary .hex file from the .out file -%.hex: %.elf - @echo Preparing: $@ - $(Q)$(OBJCOPY) -O ihex $^ $@ - -### We don't really need the .hex and .bin for the .$(TARGET) but let's make -### sure they get built -%.$(TARGET): %.elf %.hex %.bin - cp $*.elf $@ - $(Q)$(SIZE) $@ - %.jlink: sed -e 's/#OUTPUT_FILENAME#/$*.hex/' $(CONTIKI_CPU)/flash.jlink > $@ @@ -265,3 +203,5 @@ erase: $(JLINK) $(JLINK_OPTS) -CommanderScript $(CONTIKI_CPU)/erase.jlink .PHONY: softdevice.jlink + +include $(CONTIKI)/arch/cpu/arm/cortex-m/cm4/Makefile.cm4 diff --git a/arch/cpu/nrf52832/ble/ble-core.c b/arch/cpu/nrf52832/ble/ble-core.c index 8466cf8ab75bcbbe55c6cb25a8580f630819a126..9f1acdfc26d6542b2c728b38e259b763d31d8f4d 100644 --- a/arch/cpu/nrf52832/ble/ble-core.c +++ b/arch/cpu/nrf52832/ble/ble-core.c @@ -28,13 +28,7 @@ * */ /** - * \addtogroup dev - * @{ - * - * \addtogroup nrf52832 - * @{ - * - * \addtogroup nrf52832-ble Bluetooth Low Energy drivers + * \addtogroup nrf52832-ble * @{ * * \file @@ -231,8 +225,4 @@ ble_evt_dispatch(ble_evt_t *p_ble_evt) on_ble_evt(p_ble_evt); } /*---------------------------------------------------------------------------*/ -/** - * @} - * @} - * @} - */ +/** @} */ diff --git a/arch/cpu/nrf52832/ble/ble-core.h b/arch/cpu/nrf52832/ble/ble-core.h index 12c678d42acb3af7fdd23b83cbfc5543cb65afba..1e7b6127c22214e59c4e07b7dd6cee1fc6d8d7f1 100644 --- a/arch/cpu/nrf52832/ble/ble-core.h +++ b/arch/cpu/nrf52832/ble/ble-core.h @@ -28,13 +28,10 @@ * */ /** - * \addtogroup dev - * @{ - * * \addtogroup nrf52832 * @{ * - * \addtogroup nrf52832-ble Bluetooth Low Energy drivers + * \defgroup nrf52832-ble Bluetooth Low Energy drivers * @{ * * \file @@ -55,7 +52,6 @@ void ble_get_mac(uint8_t addr[8]); #endif /* DEV_BLE_H_ */ /** - * @} * @} * @} */ diff --git a/arch/platform/nrf52dk/dbg-io/dbg.c b/arch/cpu/nrf52832/dbg.c similarity index 94% rename from arch/platform/nrf52dk/dbg-io/dbg.c rename to arch/cpu/nrf52832/dbg.c index db9bb63c0ad2b0accdf61978732b1b62db181d4f..8f7be5cfc8934aeeabf1ff29e2377a895bc3d914 100644 --- a/arch/platform/nrf52dk/dbg-io/dbg.c +++ b/arch/cpu/nrf52832/dbg.c @@ -27,16 +27,12 @@ * SUCH DAMAGE. * */ - /** - * \addtogroup nrf52dk - * @{ - * - * \addtogroup nrf52dk-dbg-io Debug IO over UART + * \addtogroup nrf52832 * @{ * * \file - * Function implementations for debug io module. + * Hardware specific implementation of putchar() and puts() functions. * \author * Wojciech Bober <wojciech.bober@nordicsemi.no> * diff --git a/arch/cpu/nrf52832/dev/clock.c b/arch/cpu/nrf52832/dev/clock.c index 4ee09839da63ca14e01300e6c546b2b161bcd5a9..496668ecb6f458d376fddf1ce2790555f9d20850 100644 --- a/arch/cpu/nrf52832/dev/clock.c +++ b/arch/cpu/nrf52832/dev/clock.c @@ -53,7 +53,6 @@ #include "nrf_delay.h" #include "app_error.h" #include "contiki.h" -#include "platform-conf.h" /*---------------------------------------------------------------------------*/ const nrf_drv_rtc_t rtc = NRF_DRV_RTC_INSTANCE(PLATFORM_RTC_INSTANCE_ID); /**< RTC instance used for platform clock */ @@ -117,7 +116,7 @@ clock_init(void) rtc_config(); } /*---------------------------------------------------------------------------*/ -CCIF clock_time_t +clock_time_t clock_time(void) { return (clock_time_t)(ticks & 0xFFFFFFFF); @@ -132,7 +131,7 @@ clock_update(void) } } /*---------------------------------------------------------------------------*/ -CCIF unsigned long +unsigned long clock_seconds(void) { return (unsigned long)ticks/CLOCK_CONF_SECOND; diff --git a/arch/cpu/nrf52832/doxygen-group.txt b/arch/cpu/nrf52832/doxygen-group.txt new file mode 100644 index 0000000000000000000000000000000000000000..fad2067d6815290be76757d0645a7a4b14b6e103 --- /dev/null +++ b/arch/cpu/nrf52832/doxygen-group.txt @@ -0,0 +1,4 @@ +/** + * \defgroup nrf52832 nrf52832 SoC + * \ingroup cpu + */ diff --git a/arch/cpu/nrf52832/erase.jlink b/arch/cpu/nrf52832/erase.jlink new file mode 100644 index 0000000000000000000000000000000000000000..5f08d8d866d99258313f7c70b447ab7a065faf1c --- /dev/null +++ b/arch/cpu/nrf52832/erase.jlink @@ -0,0 +1,2 @@ +erase +q \ No newline at end of file diff --git a/arch/cpu/nrf52832/flash.jlink b/arch/cpu/nrf52832/flash.jlink new file mode 100644 index 0000000000000000000000000000000000000000..787670d55871a693acff9f3f0203ae5c662925ec --- /dev/null +++ b/arch/cpu/nrf52832/flash.jlink @@ -0,0 +1,4 @@ +loadfile #OUTPUT_FILENAME# +r +g +q \ No newline at end of file diff --git a/arch/cpu/nrf52832/int-master.c b/arch/cpu/nrf52832/int-master.c new file mode 100644 index 0000000000000000000000000000000000000000..691b2541def5bd037b27ba5b46746a51e3256fbd --- /dev/null +++ b/arch/cpu/nrf52832/int-master.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \file + * Master interrupt manipulation implementation for the nrf52832 + */ +/*---------------------------------------------------------------------------*/ +#include "nordic_common.h" +#include "contiki.h" +#include "sys/int-master.h" + +#include <stdbool.h> +/*---------------------------------------------------------------------------*/ +void +int_master_enable(void) +{ + __enable_irq(); +} +/*---------------------------------------------------------------------------*/ +int_master_status_t +int_master_read_and_disable(void) +{ + int_master_status_t primask = __get_PRIMASK(); + + __disable_irq(); + + return primask; +} +/*---------------------------------------------------------------------------*/ +void +int_master_status_set(int_master_status_t status) +{ + __set_PRIMASK(status); +} +/*---------------------------------------------------------------------------*/ +bool +int_master_is_enabled(void) +{ + return __get_PRIMASK() ? false : true; +} +/*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/nrf52832/ld/nrf52-pca10036-sd.ld b/arch/cpu/nrf52832/ld/nrf52-pca10036-sd.ld index 455749e29e501c38f4465e01b1c541c2267192d5..f3bc5bc4369e5f882fc1c16c659b637950623d0a 100644 --- a/arch/cpu/nrf52832/ld/nrf52-pca10036-sd.ld +++ b/arch/cpu/nrf52832/ld/nrf52-pca10036-sd.ld @@ -9,4 +9,8 @@ MEMORY RAM (rwx) : ORIGIN = 0x08000000, LENGTH = 0x8000 } -INCLUDE "nrf5x_common.ld" \ No newline at end of file +INCLUDE "nrf5x_common.ld" + +/* These symbols are used by the stack check library. */ +_stack = end; +_stack_origin = ORIGIN(RAM) + LENGTH(RAM); diff --git a/arch/cpu/nrf52832/ld/nrf52-pca10040-sd.ld b/arch/cpu/nrf52832/ld/nrf52-pca10040-sd.ld index f30aad455c92a59a3fa183e5d05853bc54b2a0e6..0bc7349e39d1a0bf419d5a1e8008fdf663ee9fdc 100644 --- a/arch/cpu/nrf52832/ld/nrf52-pca10040-sd.ld +++ b/arch/cpu/nrf52832/ld/nrf52-pca10040-sd.ld @@ -9,4 +9,8 @@ MEMORY RAM (rwx) : ORIGIN = 0x20002800, LENGTH = 0xD800 } -INCLUDE "nrf5x_common.ld" \ No newline at end of file +INCLUDE "nrf5x_common.ld" + +/* These symbols are used by the stack check library. */ +_stack = end; +_stack_origin = ORIGIN(RAM) + LENGTH(RAM); diff --git a/arch/cpu/nrf52832/ld/nrf52.ld b/arch/cpu/nrf52832/ld/nrf52.ld index 268794d04d0b9a388053b9d712fc01984365f770..87fc9152d5297d731584e7b7079472e5827d2aa5 100644 --- a/arch/cpu/nrf52832/ld/nrf52.ld +++ b/arch/cpu/nrf52832/ld/nrf52.ld @@ -9,4 +9,8 @@ MEMORY RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x8000 } -INCLUDE "nrf5x_common.ld" \ No newline at end of file +INCLUDE "nrf5x_common.ld" + +/* These symbols are used by the stack check library. */ +_stack = end; +_stack_origin = ORIGIN(RAM) + LENGTH(RAM); diff --git a/arch/cpu/nrf52832/mtarch.h b/arch/cpu/nrf52832/mtarch.h deleted file mode 100644 index 4f696669d5c858c64dc747ed49a9ee8b54e6ed02..0000000000000000000000000000000000000000 --- a/arch/cpu/nrf52832/mtarch.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2010, Loughborough University - Computer Science - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/* - * \file - * Stub header file for multi-threading. It doesn't do anything, it - * just exists so that mt.c can compile cleanly. - * - * This is based on the original mtarch.h for z80 by Takahide Matsutsuka - * - * \author - * George Oikonomou - <oikonomou@users.sourceforge.net> - */ -#ifndef __MTARCH_H__ -#define __MTARCH_H__ - -struct mtarch_thread { - unsigned char *sp; -}; - -#endif /* __MTARCH_H__ */ diff --git a/arch/cpu/nrf52832/nrf52832-def.h b/arch/cpu/nrf52832/nrf52832-def.h new file mode 100644 index 0000000000000000000000000000000000000000..b5eca1b5ee0cc6f8c5cebf9a3fa4471658fa84d2 --- /dev/null +++ b/arch/cpu/nrf52832/nrf52832-def.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#ifndef NRF52832_DEF_H_ +#define NRF52832_DEF_H_ +/*---------------------------------------------------------------------------*/ +#include "cm4/cm4-def.h" +/*---------------------------------------------------------------------------*/ +#if !NETSTACK_CONF_WITH_IPV6 +/* we only support IPv6 */ +#error "Only IPv6 stack is supported!" +#endif +/*---------------------------------------------------------------------------*/ +#define RTIMER_ARCH_SECOND 62500 +/*---------------------------------------------------------------------------*/ +#endif /* NRF52832_DEF_H_ */ +/*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/nrf52832/rtimer-arch.c b/arch/cpu/nrf52832/rtimer-arch.c index 78f4790f2f74076aead9737463cbbab598d56e42..02611ccbc925fad38cc1daa5ffcf79744378a8dc 100644 --- a/arch/cpu/nrf52832/rtimer-arch.c +++ b/arch/cpu/nrf52832/rtimer-arch.c @@ -44,7 +44,6 @@ #include "nrf_drv_timer.h" #include "app_error.h" #include "contiki.h" -#include "platform-conf.h" static const nrf_drv_timer_t timer = NRF_DRV_TIMER_INSTANCE(PLATFORM_TIMER_INSTANCE_ID); /**< Timer instance used for rtimer */ diff --git a/arch/dev/cc2420/cc2420.c b/arch/dev/cc2420/cc2420.c index 00ec646757267c24b2e40d29a23be605df5028a5..9310ec9e491f2f30715bff53f9262679a0f910ed 100644 --- a/arch/dev/cc2420/cc2420.c +++ b/arch/dev/cc2420/cc2420.c @@ -39,7 +39,7 @@ #include "sys/energest.h" #include "dev/leds.h" -#include "dev/spi.h" +#include "dev/spi-legacy.h" #include "cc2420.h" #include "cc2420_const.h" diff --git a/arch/dev/cc2420/cc2420.h b/arch/dev/cc2420/cc2420.h index 74b641ad676652098a9d4a87038b74fe1e718b9b..a030632a69748d4c7a3a476d5a5b860ff5f8c743 100644 --- a/arch/dev/cc2420/cc2420.h +++ b/arch/dev/cc2420/cc2420.h @@ -43,7 +43,7 @@ #define CC2420_H_ #include "contiki.h" -#include "dev/spi.h" +#include "dev/spi-legacy.h" #include "dev/radio.h" #include "cc2420_const.h" #include "lib/aes-128.h" diff --git a/arch/dev/ext-flash/README.md b/arch/dev/ext-flash/README.md new file mode 100644 index 0000000000000000000000000000000000000000..a16fb9c49ce86232e97895a3c6cd961f56ff3869 --- /dev/null +++ b/arch/dev/ext-flash/README.md @@ -0,0 +1,11 @@ +# Ext-flash Driver + +This is a generic driver for external SPI flash memories. It has been tested with the following parts: +- Winbond W25X20CL +- Winbond W25X40CL +- Macronix MX25R8035F +- Macronix MX25R1635F +- Macronix MX25R6435F +- Macronix MX25U6435F + +These parts have identical instruction sets; only the manufacturer and device ID differ, which must be specified in `board.h`. \ No newline at end of file diff --git a/arch/platform/srf06-cc26xx/common/ext-flash.c b/arch/dev/ext-flash/ext-flash.c similarity index 55% rename from arch/platform/srf06-cc26xx/common/ext-flash.c rename to arch/dev/ext-flash/ext-flash.c index 5631297ace801ec0d2dd17f513ae702e602fa299..10e953ffaef72e3e656760f1a853901d431941c1 100644 --- a/arch/platform/srf06-cc26xx/common/ext-flash.c +++ b/arch/dev/ext-flash/ext-flash.c @@ -38,12 +38,34 @@ /*---------------------------------------------------------------------------*/ #include "contiki.h" #include "ext-flash.h" -#include "ti-lib.h" -#include "board-spi.h" +#include "dev/spi.h" +#include "gpio-hal.h" +#include "sys/log.h" #include <stdint.h> #include <stdbool.h> /*---------------------------------------------------------------------------*/ +#ifndef EXT_FLASH_SPI_CONTROLLER + +#define EXT_FLASH_SPI_CONTROLLER 0xFF /* No controller */ + +#define EXT_FLASH_SPI_PIN_SCK GPIO_HAL_PIN_UNKNOWN +#define EXT_FLASH_SPI_PIN_MOSI GPIO_HAL_PIN_UNKNOWN +#define EXT_FLASH_SPI_PIN_MISO GPIO_HAL_PIN_UNKNOWN +#define EXT_FLASH_SPI_PIN_CS GPIO_HAL_PIN_UNKNOWN + +#define EXT_FLASH_DEVICE_ID 0xFF +#define EXT_FLASH_MID 0xFF + +#define EXT_FLASH_PROGRAM_PAGE_SIZE 256 +#define EXT_FLASH_ERASE_SECTOR_SIZE 4096 + +#endif /* EXT_FLASH_SPI_CONTROLLER */ +/*---------------------------------------------------------------------------*/ +/* Log configuration */ +#define LOG_MODULE "ext-flash" +#define LOG_LEVEL LOG_LEVEL_NONE +/*---------------------------------------------------------------------------*/ /* Instruction codes */ #define BLS_CODE_PROGRAM 0x02 /**< Page Program */ @@ -72,38 +94,53 @@ #define BLS_STATUS_BIT_BUSY 0x01 /**< Busy bit of the status register */ /*---------------------------------------------------------------------------*/ -/* Part specific constants */ -#define BLS_DEVICE_ID_W25X20CL 0x11 -#define BLS_DEVICE_ID_W25X40CL 0x12 -#define BLS_DEVICE_ID_MX25R8035F 0x14 -#define BLS_DEVICE_ID_MX25R1635F 0x15 - -#define BLS_WINBOND_MID 0xEF -#define BLS_MACRONIX_MID 0xC2 - -#define BLS_PROGRAM_PAGE_SIZE 256 -#define BLS_ERASE_SECTOR_SIZE 4096 -/*---------------------------------------------------------------------------*/ +#define VERIFY_PART_LOCKED -2 #define VERIFY_PART_ERROR -1 #define VERIFY_PART_POWERED_DOWN 0 #define VERIFY_PART_OK 1 /*---------------------------------------------------------------------------*/ +static spi_device_t flash_spi_configuration_default = { + .spi_controller = EXT_FLASH_SPI_CONTROLLER, + .pin_spi_sck = EXT_FLASH_SPI_PIN_SCK, + .pin_spi_miso = EXT_FLASH_SPI_PIN_MISO, + .pin_spi_mosi = EXT_FLASH_SPI_PIN_MOSI, + .pin_spi_cs = EXT_FLASH_SPI_PIN_CS, + .spi_bit_rate = 4000000, + .spi_pha = 0, + .spi_pol = 0 +}; +/*---------------------------------------------------------------------------*/ +/** + * Get spi configuration, return default configuration if NULL + */ +static spi_device_t * +get_spi_conf(spi_device_t *conf) +{ + if(conf == NULL) { + return &flash_spi_configuration_default; + } + return conf; +} +/*---------------------------------------------------------------------------*/ /** * Clear external flash CSN line */ -static void -select_on_bus(void) +static bool +select_on_bus(spi_device_t *flash_spi_configuration) { - ti_lib_gpio_clear_dio(BOARD_IOID_FLASH_CS); + if(spi_select(flash_spi_configuration) == SPI_DEV_STATUS_OK) { + return true; + } + return false; } /*---------------------------------------------------------------------------*/ /** * Set external flash CSN line */ static void -deselect(void) +deselect(spi_device_t *flash_spi_configuration) { - ti_lib_gpio_set_dio(BOARD_IOID_FLASH_CS); + spi_deselect(flash_spi_configuration); } /*---------------------------------------------------------------------------*/ /** @@ -111,20 +148,19 @@ deselect(void) * \return True when successful. */ static bool -wait_ready(void) +wait_ready(spi_device_t *flash_spi_configuration) { bool ret; const uint8_t wbuf[1] = { BLS_CODE_READ_STATUS }; - select_on_bus(); - - /* Throw away all garbages */ - board_spi_flush(); + if(select_on_bus(flash_spi_configuration) == false) { + return false; + } - ret = board_spi_write(wbuf, sizeof(wbuf)); + ret = spi_write(flash_spi_configuration, wbuf, sizeof(wbuf)); - if(ret == false) { - deselect(); + if(ret != SPI_DEV_STATUS_OK) { + deselect(flash_spi_configuration); return false; } @@ -135,19 +171,20 @@ wait_ready(void) * Thread could have yielded while waiting for flash * erase/program to complete. */ - ret = board_spi_read(&buf, sizeof(buf)); + ret = spi_read(flash_spi_configuration, &buf, sizeof(buf)); - if(ret == false) { + if(ret != SPI_DEV_STATUS_OK) { /* Error */ - deselect(); + deselect(flash_spi_configuration); return false; } + if(!(buf & BLS_STATUS_BIT_BUSY)) { /* Now ready */ break; } } - deselect(); + deselect(flash_spi_configuration); return true; } /*---------------------------------------------------------------------------*/ @@ -159,32 +196,30 @@ wait_ready(void) * was powered down */ static uint8_t -verify_part(void) +verify_part(spi_device_t *flash_spi_configuration) { const uint8_t wbuf[] = { BLS_CODE_MDID, 0xFF, 0xFF, 0x00 }; uint8_t rbuf[2] = { 0, 0 }; bool ret; - select_on_bus(); - - ret = board_spi_write(wbuf, sizeof(wbuf)); + if(select_on_bus(flash_spi_configuration) == false) { + return VERIFY_PART_LOCKED; + } - if(ret == false) { - deselect(); + if(spi_write(flash_spi_configuration, wbuf, sizeof(wbuf)) != SPI_DEV_STATUS_OK) { + deselect(flash_spi_configuration); return VERIFY_PART_ERROR; } - ret = board_spi_read(rbuf, sizeof(rbuf)); - deselect(); - - if(ret == false) { + ret = spi_read(flash_spi_configuration, rbuf, sizeof(rbuf)); + deselect(flash_spi_configuration); + if(ret != SPI_DEV_STATUS_OK) { return VERIFY_PART_ERROR; } - if((rbuf[0] != BLS_WINBOND_MID && rbuf[0] != BLS_MACRONIX_MID) || - (rbuf[1] != BLS_DEVICE_ID_W25X20CL && rbuf[1] != BLS_DEVICE_ID_W25X40CL - && rbuf[1] != BLS_DEVICE_ID_MX25R8035F - && rbuf[1] != BLS_DEVICE_ID_MX25R1635F)) { + LOG_DBG("Verify: %02x %02x\n", rbuf[0], rbuf[1]); + + if(rbuf[0] != EXT_FLASH_MID || rbuf[1] != EXT_FLASH_DEVICE_ID) { return VERIFY_PART_POWERED_DOWN; } return VERIFY_PART_OK; @@ -194,34 +229,41 @@ verify_part(void) * \brief Put the device in power save mode. No access to data; only * the status register is accessible. */ -static void -power_down(void) +static bool +power_down(spi_device_t *flash_spi_configuration) { uint8_t cmd; uint8_t i; /* First, wait for the device to be ready */ - if(wait_ready() == false) { + if(wait_ready(flash_spi_configuration) == false) { /* Entering here will leave the device in standby instead of powerdown */ - return; + return false; } cmd = BLS_CODE_PD; - select_on_bus(); - board_spi_write(&cmd, sizeof(cmd)); - deselect(); + if(select_on_bus(flash_spi_configuration) == false) { + return false; + } + + if(spi_write_byte(flash_spi_configuration, cmd) != SPI_DEV_STATUS_OK) { + deselect(flash_spi_configuration); + return false; + } + deselect(flash_spi_configuration); i = 0; while(i < 10) { - if(verify_part() == VERIFY_PART_POWERED_DOWN) { + if(verify_part(flash_spi_configuration) == VERIFY_PART_POWERED_DOWN) { /* Device is powered down */ - return; + return true; } i++; } /* Should not be required */ - deselect(); + deselect(flash_spi_configuration); + return false; } /*---------------------------------------------------------------------------*/ /** @@ -229,20 +271,23 @@ power_down(void) * \return True if the command was written successfully */ static bool -power_standby(void) +power_standby(spi_device_t *flash_spi_configuration) { uint8_t cmd; bool success; cmd = BLS_CODE_RPD; - select_on_bus(); - success = board_spi_write(&cmd, sizeof(cmd)); + if(select_on_bus(flash_spi_configuration) == false) { + return false; + } + + success = (spi_write(flash_spi_configuration, &cmd, sizeof(cmd)) == SPI_DEV_STATUS_OK); if(success) { - success = wait_ready() == true ? true : false; + success = wait_ready(flash_spi_configuration) == true ? true : false; } - deselect(); + deselect(flash_spi_configuration); return success; } @@ -252,14 +297,17 @@ power_standby(void) * \return True when successful. */ static bool -write_enable(void) +write_enable(spi_device_t *flash_spi_configuration) { bool ret; const uint8_t wbuf[] = { BLS_CODE_WRITE_ENABLE }; - select_on_bus(); - ret = board_spi_write(wbuf, sizeof(wbuf)); - deselect(); + if(select_on_bus(flash_spi_configuration) == false) { + return false; + } + + ret = (spi_write(flash_spi_configuration, wbuf, sizeof(wbuf)) == SPI_DEV_STATUS_OK); + deselect(flash_spi_configuration); if(ret == false) { return false; @@ -268,39 +316,66 @@ write_enable(void) } /*---------------------------------------------------------------------------*/ bool -ext_flash_open() +ext_flash_open(spi_device_t *conf) { - board_spi_open(4000000, BOARD_IOID_SPI_CLK_FLASH); + spi_device_t *flash_spi_configuration; + + flash_spi_configuration = get_spi_conf(conf); - /* GPIO pin configuration */ - ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_FLASH_CS); + /* Check if platform has ext-flash */ + if(flash_spi_configuration->pin_spi_sck == GPIO_HAL_PIN_UNKNOWN) { + return false; + } + if(spi_acquire(flash_spi_configuration) != SPI_DEV_STATUS_OK) { + return false; + } /* Default output to clear chip select */ - deselect(); + deselect(flash_spi_configuration); /* Put the part is standby mode */ - power_standby(); + power_standby(flash_spi_configuration); - return verify_part() == VERIFY_PART_OK ? true : false; + if(verify_part(flash_spi_configuration) == VERIFY_PART_OK) { + return true; + } + + /* Failed to verify */ + spi_release(flash_spi_configuration); + return false; } /*---------------------------------------------------------------------------*/ -void -ext_flash_close() +bool +ext_flash_close(spi_device_t *conf) { + bool ret; + spi_device_t *flash_spi_configuration; + + flash_spi_configuration = get_spi_conf(conf); + /* Put the part in low power mode */ - power_down(); + ret = power_down(flash_spi_configuration); + + /* SPI is released no matter if power_down() succeeds or fails */ + if(spi_release(flash_spi_configuration) != SPI_DEV_STATUS_OK) { + return false; + } - board_spi_close(); + return ret; } /*---------------------------------------------------------------------------*/ bool -ext_flash_read(size_t offset, size_t length, uint8_t *buf) +ext_flash_read(spi_device_t *conf, uint32_t offset, uint32_t length, uint8_t *buf) { uint8_t wbuf[4]; + bool ret; + + spi_device_t *flash_spi_configuration; + + flash_spi_configuration = get_spi_conf(conf); /* Wait till previous erase/program operation completes */ - bool ret = wait_ready(); - if(ret == false) { + if(wait_ready(flash_spi_configuration) == false) { return false; } @@ -313,41 +388,44 @@ ext_flash_read(size_t offset, size_t length, uint8_t *buf) wbuf[2] = (offset >> 8) & 0xff; wbuf[3] = offset & 0xff; - select_on_bus(); + if(select_on_bus(flash_spi_configuration) == false) { + return false; + } - if(board_spi_write(wbuf, sizeof(wbuf)) == false) { + if(spi_write(flash_spi_configuration, wbuf, sizeof(wbuf)) != SPI_DEV_STATUS_OK) { /* failure */ - deselect(); + deselect(flash_spi_configuration); return false; } - ret = board_spi_read(buf, length); + ret = (spi_read(flash_spi_configuration, buf, length) == SPI_DEV_STATUS_OK); - deselect(); + deselect(flash_spi_configuration); return ret; } /*---------------------------------------------------------------------------*/ bool -ext_flash_write(size_t offset, size_t length, const uint8_t *buf) +ext_flash_write(spi_device_t *conf, uint32_t offset, uint32_t length, const uint8_t *buf) { uint8_t wbuf[4]; - bool ret; - size_t ilen; /* interim length per instruction */ + uint32_t ilen; /* interim length per instruction */ + + spi_device_t *flash_spi_configuration; + + flash_spi_configuration = get_spi_conf(conf); while(length > 0) { /* Wait till previous erase/program operation completes */ - ret = wait_ready(); - if(ret == false) { + if(wait_ready(flash_spi_configuration) == false) { return false; } - ret = write_enable(); - if(ret == false) { + if(write_enable(flash_spi_configuration) == false) { return false; } - ilen = BLS_PROGRAM_PAGE_SIZE - (offset % BLS_PROGRAM_PAGE_SIZE); + ilen = EXT_FLASH_PROGRAM_PAGE_SIZE - (offset % EXT_FLASH_PROGRAM_PAGE_SIZE); if(length < ilen) { ilen = length; } @@ -365,28 +443,30 @@ ext_flash_write(size_t offset, size_t length, const uint8_t *buf) * is not imposed here since above instructions * should be enough to delay * as much. */ - select_on_bus(); + if(select_on_bus(flash_spi_configuration) == false) { + return false; + } - if(board_spi_write(wbuf, sizeof(wbuf)) == false) { + if(spi_write(flash_spi_configuration, wbuf, sizeof(wbuf)) != SPI_DEV_STATUS_OK) { /* failure */ - deselect(); + deselect(flash_spi_configuration); return false; } - if(board_spi_write(buf, ilen) == false) { + if(spi_write(flash_spi_configuration, buf, ilen) != SPI_DEV_STATUS_OK) { /* failure */ - deselect(); + deselect(flash_spi_configuration); return false; } buf += ilen; - deselect(); + deselect(flash_spi_configuration); } return true; } /*---------------------------------------------------------------------------*/ bool -ext_flash_erase(size_t offset, size_t length) +ext_flash_erase(spi_device_t *conf, uint32_t offset, uint32_t length) { /* * Note that Block erase might be more efficient when the floor map @@ -394,24 +474,25 @@ ext_flash_erase(size_t offset, size_t length) * sector erase is used blindly. */ uint8_t wbuf[4]; - bool ret; - size_t i, numsectors; - size_t endoffset = offset + length - 1; + uint32_t i, numsectors; + uint32_t endoffset = offset + length - 1; - offset = (offset / BLS_ERASE_SECTOR_SIZE) * BLS_ERASE_SECTOR_SIZE; - numsectors = (endoffset - offset + BLS_ERASE_SECTOR_SIZE - 1) / BLS_ERASE_SECTOR_SIZE; + spi_device_t *flash_spi_configuration; + + flash_spi_configuration = get_spi_conf(conf); + + offset = (offset / EXT_FLASH_ERASE_SECTOR_SIZE) * EXT_FLASH_ERASE_SECTOR_SIZE; + numsectors = (endoffset - offset + EXT_FLASH_ERASE_SECTOR_SIZE - 1) / EXT_FLASH_ERASE_SECTOR_SIZE; wbuf[0] = BLS_CODE_SECTOR_ERASE; for(i = 0; i < numsectors; i++) { /* Wait till previous erase/program operation completes */ - ret = wait_ready(); - if(ret == false) { + if(wait_ready(flash_spi_configuration) == false) { return false; } - ret = write_enable(); - if(ret == false) { + if(write_enable(flash_spi_configuration) == false) { return false; } @@ -419,37 +500,37 @@ ext_flash_erase(size_t offset, size_t length) wbuf[2] = (offset >> 8) & 0xff; wbuf[3] = offset & 0xff; - select_on_bus(); + if(select_on_bus(flash_spi_configuration) == false) { + return false; + } - if(board_spi_write(wbuf, sizeof(wbuf)) == false) { + if(spi_write(flash_spi_configuration, wbuf, sizeof(wbuf)) != SPI_DEV_STATUS_OK) { /* failure */ - deselect(); + deselect(flash_spi_configuration); return false; } - deselect(); + deselect(flash_spi_configuration); - offset += BLS_ERASE_SECTOR_SIZE; + offset += EXT_FLASH_ERASE_SECTOR_SIZE; } return true; } /*---------------------------------------------------------------------------*/ bool -ext_flash_test(void) +ext_flash_init(spi_device_t *conf) { - bool ret; + if(ext_flash_open(conf) == false) { + return false; + } - ret = ext_flash_open(); - ext_flash_close(); + if(ext_flash_close(conf) == false) { + return false; + } - return ret; -} -/*---------------------------------------------------------------------------*/ -void -ext_flash_init() -{ - ext_flash_open(); - ext_flash_close(); + LOG_INFO("Flash init successful\n"); + + return true; } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/arch/platform/srf06-cc26xx/common/ext-flash.h b/arch/dev/ext-flash/ext-flash.h similarity index 82% rename from arch/platform/srf06-cc26xx/common/ext-flash.h rename to arch/dev/ext-flash/ext-flash.h index 5f2717edb29715b326b0ffd1f62d5551a81103bd..20748a2f0492ce59e9e575d4cd90466a2cdbd8ad 100644 --- a/arch/platform/srf06-cc26xx/common/ext-flash.h +++ b/arch/dev/ext-flash/ext-flash.h @@ -42,25 +42,30 @@ #ifndef EXT_FLASH_H_ #define EXT_FLASH_H_ /*---------------------------------------------------------------------------*/ +#include "dev/spi.h" #include <stdint.h> #include <stdlib.h> #include <stdbool.h> /*---------------------------------------------------------------------------*/ /** * \brief Initialize storage driver. + * \param conf SPI bus configuration struct. NULL for default. * \return True when successful. */ -bool ext_flash_open(void); +bool ext_flash_open(spi_device_t *conf); /** * \brief Close the storage driver + * \param conf SPI bus configuration struct. NULL for default. + * \return True when successful. * * This call will put the device in its lower power mode (power down). */ -void ext_flash_close(void); +bool ext_flash_close(spi_device_t *conf); /** * \brief Read storage content + * \param conf SPI bus configuration struct. NULL for default. * \param offset Address to read from * \param length Number of bytes to read * \param buf Buffer where to store the read bytes @@ -68,10 +73,11 @@ void ext_flash_close(void); * * buf must be allocated by the caller */ -bool ext_flash_read(size_t offset, size_t length, uint8_t *buf); +bool ext_flash_read(spi_device_t *conf, uint32_t offset, uint32_t length, uint8_t *buf); /** * \brief Erase storage sectors corresponding to the range. + * \param conf SPI bus configuration struct. NULL for default. * \param offset Address to start erasing * \param length Number of bytes to erase * \return True when successful. @@ -79,26 +85,22 @@ bool ext_flash_read(size_t offset, size_t length, uint8_t *buf); * The erase operation will be sector-wise, therefore a call to this function * will generally start the erase procedure at an address lower than offset */ -bool ext_flash_erase(size_t offset, size_t length); +bool ext_flash_erase(spi_device_t *conf, uint32_t offset, uint32_t length); /** * \brief Write to storage sectors. + * \param conf SPI bus configuration struct. NULL for default. * \param offset Address to write to * \param length Number of bytes to write * \param buf Buffer holding the bytes to be written * * \return True when successful. */ -bool ext_flash_write(size_t offset, size_t length, const uint8_t *buf); - -/** - * \brief Test the flash (power on self-test) - * \return True when successful. - */ -bool ext_flash_test(void); +bool ext_flash_write(spi_device_t *conf, uint32_t offset, uint32_t length, const uint8_t *buf); /** * \brief Initialise the external flash + * \param conf SPI bus configuration struct. NULL for default. * * This function will explicitly put the part in its lowest power mode * (power-down). @@ -106,7 +108,7 @@ bool ext_flash_test(void); * In order to perform any operation, the caller must first wake the device * up by calling ext_flash_open() */ -void ext_flash_init(void); +bool ext_flash_init(spi_device_t *conf); /*---------------------------------------------------------------------------*/ #endif /* EXT_FLASH_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/arch/dev/rgb-led/rgb-led.c b/arch/dev/rgb-led/rgb-led.c new file mode 100644 index 0000000000000000000000000000000000000000..521583022d0430496321e4c5820251d99658aea4 --- /dev/null +++ b/arch/dev/rgb-led/rgb-led.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup rgb-led + * @{ + * + * \file + * Implementation of the RGB LED driver. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/leds.h" +#include "dev/rgb-led/rgb-led.h" +/*---------------------------------------------------------------------------*/ +void +rgb_led_off(void) +{ + leds_off(LEDS_ALL); +} +/*----------------------------------------------------------------------------*/ +void +rgb_led_set(uint8_t colour) +{ + leds_mask_t leds = + ((colour & RGB_LED_RED) ? LEDS_RED : LEDS_COLOUR_NONE) | + ((colour & RGB_LED_GREEN) ? LEDS_GREEN : LEDS_COLOUR_NONE) | + ((colour & RGB_LED_BLUE) ? LEDS_BLUE : LEDS_COLOUR_NONE); + + leds_off(LEDS_ALL); + leds_on(leds); +} +/*----------------------------------------------------------------------------*/ +/** @} */ diff --git a/arch/dev/rgb-led/rgb-led.h b/arch/dev/rgb-led/rgb-led.h new file mode 100644 index 0000000000000000000000000000000000000000..d0cd81d38c51a2cbcdfc4458d2497988bb792b33 --- /dev/null +++ b/arch/dev/rgb-led/rgb-led.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#ifndef RGB_LED_H_ +#define RGB_LED_H_ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup dev + * @{ + */ +/*---------------------------------------------------------------------------*/ +/** + * \defgroup rgb-led Generic RGB LED driver + * + * This is a driver for a tri-color RGB LED part, such as for example the + * Broadcom (ex Avago Technologies) PLCC-4 Tricolor Black Surface LED present + * on all Zolertia Zoul-based boards. + * + * + * This driver sits on top of the LED HAL. Therefore, any port that wishes to + * use this driver should first implement the GPIO HAL and the new LED API. + * This driver will set the colour of the RGB LED by using combinations of + * LED_RED, LED_GREEN and LED_BLUE. Therefore, those must be correctly defined + * by the platform configuration. + * @{ + * + * \file + * Header file for the RGB LED driver. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include <stdint.h> +/*---------------------------------------------------------------------------*/ +#define RGB_LED_RED 1 +#define RGB_LED_GREEN 2 +#define RGB_LED_BLUE 4 +#define RGB_LED_MAGENTA (RGB_LED_RED | RGB_LED_BLUE) +#define RGB_LED_YELLOW (RGB_LED_RED | RGB_LED_GREEN) +#define RGB_LED_CYAN (RGB_LED_GREEN | RGB_LED_BLUE ) +#define RGB_LED_WHITE (RGB_LED_RED | RGB_LED_GREEN | RGB_LED_BLUE) +/*---------------------------------------------------------------------------*/ +/** + * \brief Turn off the RGB LED + */ +void rgb_led_off(void); + +/** + * \brief Set the colour of the RGB LED + * \param colour The colour to set + * + * \e colour can take the value of one of the RGB_LED_xyz defines. + */ +void rgb_led_set(uint8_t colour); +/*---------------------------------------------------------------------------*/ +#endif /* RGB_LED_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/arch/platform/cc2538dk/Makefile.cc2538dk b/arch/platform/cc2538dk/Makefile.cc2538dk index a9870079f3b474087c14e2a4f2b8ce13e61a514f..c452ccfafaa741b3567f227cc34bcb958937369e 100644 --- a/arch/platform/cc2538dk/Makefile.cc2538dk +++ b/arch/platform/cc2538dk/Makefile.cc2538dk @@ -6,21 +6,18 @@ endif CONTIKI_TARGET_DIRS = . dev -CONTIKI_TARGET_SOURCEFILES += leds.c leds-arch.c +CONTIKI_TARGET_SOURCEFILES += leds-arch.c CONTIKI_TARGET_SOURCEFILES += platform.c CONTIKI_TARGET_SOURCEFILES += sensors.c smartrf-sensors.c -CONTIKI_TARGET_SOURCEFILES += button-sensor.c als-sensor.c +CONTIKI_TARGET_SOURCEFILES += board-buttons.c als-sensor.c CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) -CLEAN += *.cc2538dk - ### Define the CPU directory CONTIKI_CPU=$(CONTIKI)/arch/cpu/cc2538 include $(CONTIKI_CPU)/Makefile.cc2538 -MODULES += os/net os/net/mac os/net/mac/framer \ - os/storage/cfs +MODULES += os/storage/cfs PYTHON = python BSL_FLAGS += -e -w -v diff --git a/arch/platform/cc2538dk/contiki-conf.h b/arch/platform/cc2538dk/contiki-conf.h index 0c956efff7ba0e6f9d5c694ab792663c8250c12c..649fde347b53f80b2d9ae7e1bd297b0edbbed677 100644 --- a/arch/platform/cc2538dk/contiki-conf.h +++ b/arch/platform/cc2538dk/contiki-conf.h @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ /** * \addtogroup cc2538dk * @{ @@ -10,57 +41,14 @@ #include <stdint.h> #include <string.h> +#include <inttypes.h> /*---------------------------------------------------------------------------*/ /* Include Project Specific conf */ #ifdef PROJECT_CONF_PATH #include PROJECT_CONF_PATH #endif /* PROJECT_CONF_PATH */ /*---------------------------------------------------------------------------*/ -/** - * \name Compiler configuration and platform-specific type definitions - * - * Those values are not meant to be modified by the user - * @{ - */ -#define CLOCK_CONF_SECOND 128 - -/* Compiler configurations */ -#define CCIF -#define CLIF - -/* Platform typedefs */ -typedef uint32_t clock_time_t; -typedef uint32_t uip_stats_t; - -/* - * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define - * RTIMER_CLOCK_DIFF to override this - */ -typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_DIFF(a,b) ((int32_t)((a)-(b))) -/** @} */ -/*---------------------------------------------------------------------------*/ -/* 352us from calling transmit() until the SFD byte has been sent */ -#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(352)) -/* 192us as in datasheet but ACKs are not always received, so adjusted to 250us */ -#define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(250)) -#define RADIO_DELAY_BEFORE_DETECT 0 -#ifndef TSCH_CONF_BASE_DRIFT_PPM -/* The drift compared to "true" 10ms slots. - * Enable adaptive sync to enable compensation for this. - * Slot length 10000 usec - * 328 ticks - * Tick duration 30.517578125 usec - * Real slot duration 10009.765625 usec - * Target - real duration = -9.765625 usec - * TSCH_CONF_BASE_DRIFT_PPM -977 - */ -#define TSCH_CONF_BASE_DRIFT_PPM -977 -#endif - -#if MAC_CONF_WITH_TSCH -#define TSCH_CONF_HW_FRAME_FILTERING 0 -#endif /* MAC_CONF_WITH_TSCH */ +#include "cc2538-def.h" /*---------------------------------------------------------------------------*/ /** * \name Serial Boot Loader Backdoor configuration @@ -68,7 +56,7 @@ typedef uint32_t rtimer_clock_t; * @{ */ #ifndef FLASH_CCA_CONF_BOOTLDR_BACKDOOR -#define FLASH_CCA_CONF_BOOTLDR_BACKDOOR 1 /**<Enable the boot loader backdoor */ +#define FLASH_CCA_CONF_BOOTLDR_BACKDOOR 1 /**<Enable the boot loader backdoor */ #endif #ifndef FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN @@ -90,274 +78,12 @@ typedef uint32_t rtimer_clock_t; #endif /** @} */ /*---------------------------------------------------------------------------*/ -/** - * \name Watchdog Timer configuration - * - * @{ - */ -#ifndef WATCHDOG_CONF_ENABLE -#define WATCHDOG_CONF_ENABLE 1 /**< Enable the watchdog timer */ -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name USB 'core' configuration - * - * Those values are not meant to be modified by the user, except where stated - * otherwise - * @{ - */ -#define CTRL_EP_SIZE 8 -#define USB_EP1_SIZE 32 -#define USB_EP2_SIZE 64 -#define USB_EP3_SIZE 64 -#define USB_ARCH_WRITE_NOTIFY 0 - -#ifndef USB_ARCH_CONF_DMA -#define USB_ARCH_CONF_DMA 1 /**< Change to Enable/Disable USB DMA */ - -#endif -/** @} */ - -/*---------------------------------------------------------------------------*/ -/** - * \name uDMA Configuration and channel allocations - * - * @{ - */ -#define USB_ARCH_CONF_RX_DMA_CHAN 0 /**< USB -> RAM DMA channel */ -#define USB_ARCH_CONF_TX_DMA_CHAN 1 /**< RAM -> USB DMA channel */ -#define CC2538_RF_CONF_TX_DMA_CHAN 2 /**< RF -> RAM DMA channel */ -#define CC2538_RF_CONF_RX_DMA_CHAN 3 /**< RAM -> RF DMA channel */ -#define UDMA_CONF_MAX_CHANNEL CC2538_RF_CONF_RX_DMA_CHAN -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name Character I/O Configuration - * - * @{ - */ -#ifndef UART_CONF_ENABLE -#define UART_CONF_ENABLE 1 /**< Enable/Disable UART I/O */ -#endif - -#ifndef UART0_CONF_BAUD_RATE -#define UART0_CONF_BAUD_RATE 115200 /**< Default UART0 baud rate */ -#endif - -#ifndef UART1_CONF_BAUD_RATE -#define UART1_CONF_BAUD_RATE 115200 /**< Default UART1 baud rate */ -#endif - -#ifndef SLIP_ARCH_CONF_USB -#define SLIP_ARCH_CONF_USB 0 /**< SLIP over UART by default */ -#endif - -#ifndef DBG_CONF_USB -#define DBG_CONF_USB 0 /**< All debugging over UART by default */ -#endif - -#ifndef SERIAL_LINE_CONF_UART -#define SERIAL_LINE_CONF_UART 0 /**< UART to use with serial line */ -#endif - -#if !SLIP_ARCH_CONF_USB -#ifndef SLIP_ARCH_CONF_UART -#define SLIP_ARCH_CONF_UART 0 /**< UART to use with SLIP */ -#endif -#endif - -#if !DBG_CONF_USB -#ifndef DBG_CONF_UART -#define DBG_CONF_UART 0 /**< UART to use for debugging */ -#endif -#endif - -#ifndef UART1_CONF_UART -#define UART1_CONF_UART 0 /**< UART to use for examples relying on - the uart1_* API */ -#endif - -#ifndef SLIP_ARCH_CONF_ENABLED -/* - * Determine whether we need SLIP - * This will keep working while UIP_FALLBACK_INTERFACE and CMD_CONF_OUTPUT - * keep using SLIP - */ -#if defined (UIP_FALLBACK_INTERFACE) || defined (CMD_CONF_OUTPUT) -#define SLIP_ARCH_CONF_ENABLED 1 -#endif -#endif - -/** - * \brief Define this as 1 to build a headless node. - * - * The UART will not be initialised its clock will be gated, offering some - * energy savings. The USB will not be initialised either - */ -#ifndef CC2538_CONF_QUIET -#define CC2538_CONF_QUIET 0 -#endif - -/* CC2538_CONF_QUIET is hard and overrides all other related defines */ -#if CC2538_CONF_QUIET -#undef USB_SERIAL_CONF_ENABLE -#define USB_SERIAL_CONF_ENABLE 0 - -#undef UART_CONF_ENABLE -#define UART_CONF_ENABLE 0 -#endif /* CC2538_CONF_QUIET */ - -/** - * \brief Enable the USB core only if we need it - */ -#ifndef USB_SERIAL_CONF_ENABLE -#define USB_SERIAL_CONF_ENABLE \ - ((SLIP_ARCH_CONF_USB && SLIP_ARCH_CONF_ENABLED) || \ - (MAC_CONF_WITH_TSCH && (SLIP_ARCH_CONF_ENABLED || BUILD_WITH_SHELL)) || \ - DBG_CONF_USB) -#endif - -/* - * If debugging and SLIP use the same peripheral, this will be 1. Don't modify - * this - */ -#if SLIP_ARCH_CONF_ENABLED -#define DBG_CONF_SLIP_MUX (SLIP_ARCH_CONF_USB == DBG_CONF_USB && \ - (SLIP_ARCH_CONF_USB || \ - SLIP_ARCH_CONF_UART == DBG_CONF_UART)) -#endif - -/* - * Automatic detection of whether a specific UART is in use - */ -#define UART_IN_USE_BY_SERIAL_LINE(u) (SERIAL_LINE_CONF_UART == (u)) -#define UART_IN_USE_BY_SLIP(u) (SLIP_ARCH_CONF_ENABLED && \ - !SLIP_ARCH_CONF_USB && \ - SLIP_ARCH_CONF_UART == (u)) -#define UART_IN_USE_BY_DBG(u) (!DBG_CONF_USB && DBG_CONF_UART == (u)) -#define UART_IN_USE_BY_UART1(u) (UART1_CONF_UART == (u)) - -#define UART_IN_USE(u) ( \ - UART_CONF_ENABLE && \ - (UART_IN_USE_BY_SERIAL_LINE(u) || \ - UART_IN_USE_BY_SLIP(u) || \ - UART_IN_USE_BY_DBG(u) || \ - UART_IN_USE_BY_UART1(u)) \ -) -/** @} */ -/*---------------------------------------------------------------------------*/ /* board.h assumes that basic configuration is done */ #include "board.h" /*---------------------------------------------------------------------------*/ - -#define NETSTACK_CONF_RADIO cc2538_rf_driver -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name LPM configuration - * @{ - */ -#ifndef LPM_CONF_ENABLE -#define LPM_CONF_ENABLE 1 /**< Set to 0 to disable LPM entirely */ -#endif - -/** - * \brief Maximum PM - * - * The SoC will never drop to a Power Mode deeper than the one specified here. - * 0 for PM0, 1 for PM1 and 2 for PM2 - */ -#ifndef LPM_CONF_MAX_PM -#define LPM_CONF_MAX_PM 1 -#endif - -#ifndef LPM_CONF_STATS -#define LPM_CONF_STATS 0 /**< Set to 1 to enable LPM-related stats */ -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name IEEE address configuration - * - * Used to generate our link-layer & IPv6 address - * @{ - */ -/** - * \brief Location of the IEEE address - * 0 => Read from InfoPage, - * 1 => Use a hardcoded address, configured by IEEE_ADDR_CONF_ADDRESS - */ -#ifndef IEEE_ADDR_CONF_HARDCODED -#define IEEE_ADDR_CONF_HARDCODED 0 -#endif - -/** - * \brief The hardcoded IEEE address to be used when IEEE_ADDR_CONF_HARDCODED - * is defined as 1 - */ -#ifndef IEEE_ADDR_CONF_ADDRESS -#define IEEE_ADDR_CONF_ADDRESS { 0x00, 0x12, 0x4B, 0x00, 0x89, 0xAB, 0xCD, 0xEF } -#endif - -/** - * \brief Location of the IEEE address in the InfoPage when - * IEEE_ADDR_CONF_HARDCODED is defined as 0 - * 0 => Use the primary address location - * 1 => Use the secondary address location - */ -#ifndef IEEE_ADDR_CONF_USE_SECONDARY_LOCATION -#define IEEE_ADDR_CONF_USE_SECONDARY_LOCATION 0 -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name RF configuration - * - * @{ - */ -/* RF Config */ -#ifdef RF_CHANNEL -#define CC2538_RF_CONF_CHANNEL RF_CHANNEL -#endif - -#ifndef CC2538_RF_CONF_CHANNEL -#define CC2538_RF_CONF_CHANNEL 25 -#endif /* CC2538_RF_CONF_CHANNEL */ - -#ifndef CC2538_RF_CONF_AUTOACK -#define CC2538_RF_CONF_AUTOACK 1 /**< RF H/W generates ACKs */ -#endif /* CC2538_CONF_AUTOACK */ - -#ifndef CC2538_RF_CONF_TX_USE_DMA -#define CC2538_RF_CONF_TX_USE_DMA 1 /**< RF TX over DMA */ -#endif - -#ifndef CC2538_RF_CONF_RX_USE_DMA -#define CC2538_RF_CONF_RX_USE_DMA 1 /**< RF RX over DMA */ -#endif -/** @} */ - -/*---------------------------------------------------------------------------*/ -/** - * \name Security - * - * @{ - */ -#ifndef CRYPTO_CONF_INIT -#define CRYPTO_CONF_INIT 1 /**< Whether to init cryptoprocessor */ -#endif - -#ifndef AES_128_CONF -#define AES_128_CONF cc2538_aes_128_driver /**< AES-128 driver */ -#endif - -#ifndef CCM_STAR_CONF -#define CCM_STAR_CONF cc2538_ccm_star_driver /**< AES-CCM* driver */ -#endif -/** @} */ +/* Include CPU-related configuration */ +#include "cc2538-conf.h" /*---------------------------------------------------------------------------*/ - #endif /* CONTIKI_CONF_H_ */ - +/*---------------------------------------------------------------------------*/ /** @} */ diff --git a/arch/platform/cc2538dk/dev/board-buttons.c b/arch/platform/cc2538dk/dev/board-buttons.c new file mode 100644 index 0000000000000000000000000000000000000000..6afc915dfbb6d55ea58f53e8bc513ff33a3705d3 --- /dev/null +++ b/arch/platform/cc2538dk/dev/board-buttons.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc2538-smartrf + * @{ + * + * \defgroup cc2538-smartrf-buttons SmartRF06EB Buttons + * + * Generic module controlling buttons on the SmartRF06EB + * @{ + * + * \file + * Defines SmartRF06EB buttons for use with the button HAL + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/button-hal.h" +/*---------------------------------------------------------------------------*/ +BUTTON_HAL_BUTTON(key_left, "Key Left", \ + GPIO_PORT_PIN_TO_GPIO_HAL_PIN(BUTTON_LEFT_PORT, BUTTON_LEFT_PIN), \ + GPIO_HAL_PIN_CFG_PULL_UP, BUTTON_HAL_ID_BUTTON_ZERO, true); +BUTTON_HAL_BUTTON(key_right, "Key Right", \ + GPIO_PORT_PIN_TO_GPIO_HAL_PIN(BUTTON_RIGHT_PORT, BUTTON_RIGHT_PIN), \ + GPIO_HAL_PIN_CFG_PULL_UP, BUTTON_HAL_ID_BUTTON_ONE, true); +BUTTON_HAL_BUTTON(key_up, "Key Up", \ + GPIO_PORT_PIN_TO_GPIO_HAL_PIN(BUTTON_UP_PORT, BUTTON_UP_PIN), \ + GPIO_HAL_PIN_CFG_PULL_UP, BUTTON_HAL_ID_BUTTON_TWO, true); +BUTTON_HAL_BUTTON(key_down, "Key Down", \ + GPIO_PORT_PIN_TO_GPIO_HAL_PIN(BUTTON_DOWN_PORT, BUTTON_DOWN_PIN), \ + GPIO_HAL_PIN_CFG_PULL_UP, BUTTON_HAL_ID_BUTTON_THREE, true); +BUTTON_HAL_BUTTON(key_select, "Key Select", \ + GPIO_PORT_PIN_TO_GPIO_HAL_PIN(BUTTON_SELECT_PORT, BUTTON_SELECT_PIN), \ + GPIO_HAL_PIN_CFG_PULL_UP, BUTTON_HAL_ID_BUTTON_FOUR, true); +/*---------------------------------------------------------------------------*/ +BUTTON_HAL_BUTTONS(&key_left, &key_right, &key_up, &key_down, &key_select); +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/arch/platform/cc2538dk/dev/board.h b/arch/platform/cc2538dk/dev/board.h index 3b3836c58fcc53b2d2cac8984adad49ad2a08a37..80f036fd7c904c2fafd330f1f1fbc691e313f036 100644 --- a/arch/platform/cc2538dk/dev/board.h +++ b/arch/platform/cc2538dk/dev/board.h @@ -71,27 +71,25 @@ * @{ */ /*---------------------------------------------------------------------------*/ -/* Some files include leds.h before us, so we need to get rid of defaults in - * leds.h before we provide correct definitions */ -#undef LEDS_GREEN -#undef LEDS_YELLOW -#undef LEDS_RED -#undef LEDS_CONF_ALL +#define LEDS_CONF_YELLOW 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_ORANGE 4 -#define LEDS_YELLOW 2 /**< LED2 (Yellow) -> PC1 */ -#define LEDS_GREEN 4 /**< LED3 (Green) -> PC2 */ -#define LEDS_ORANGE 8 /**< LED4 (Orange) -> PC3 */ +#define LEDS_ARCH_L1_PORT GPIO_C_NUM +#define LEDS_ARCH_L1_PIN 1 +#define LEDS_ARCH_L2_PORT GPIO_C_NUM +#define LEDS_ARCH_L2_PIN 2 +#define LEDS_ARCH_L3_PORT GPIO_C_NUM +#define LEDS_ARCH_L3_PIN 3 #if USB_SERIAL_CONF_ENABLE -#define LEDS_CONF_ALL 14 -#define LEDS_RED LEDS_ORANGE +#define LEDS_CONF_COUNT 3 #else -#define LEDS_CONF_ALL 15 -#define LEDS_RED 1 /**< LED1 (Red) -> PC0 */ +#define LEDS_ARCH_L4_PORT GPIO_C_NUM +#define LEDS_ARCH_L4_PIN 0 +#define LEDS_CONF_RED 8 +#define LEDS_CONF_COUNT 4 #endif - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 /** @} */ /*---------------------------------------------------------------------------*/ /** \name USB configuration @@ -165,6 +163,7 @@ /* Notify various examples that we have Buttons */ #define PLATFORM_HAS_BUTTON 1 +#define PLATFORM_SUPPORTS_BUTTON_HAL 1 /** @} */ /*---------------------------------------------------------------------------*/ /** diff --git a/arch/platform/cc2538dk/dev/button-sensor.c b/arch/platform/cc2538dk/dev/button-sensor.c deleted file mode 100644 index 14d4e7d15088c8016f8c9826b93aca34fedc80e5..0000000000000000000000000000000000000000 --- a/arch/platform/cc2538dk/dev/button-sensor.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \addtogroup cc2538dk-button-sensor - * @{ - * - * \file - * Driver for the SmartRF06EB buttons - */ -#include "contiki.h" -#include "dev/nvic.h" -#include "dev/ioc.h" -#include "dev/gpio.h" -#include "dev/button-sensor.h" -#include "sys/timer.h" - -#include <stdint.h> -#include <string.h> - -#define BUTTON_SELECT_PORT_BASE GPIO_PORT_TO_BASE(BUTTON_SELECT_PORT) -#define BUTTON_SELECT_PIN_MASK GPIO_PIN_MASK(BUTTON_SELECT_PIN) - -#define BUTTON_LEFT_PORT_BASE GPIO_PORT_TO_BASE(BUTTON_LEFT_PORT) -#define BUTTON_LEFT_PIN_MASK GPIO_PIN_MASK(BUTTON_LEFT_PIN) - -#define BUTTON_RIGHT_PORT_BASE GPIO_PORT_TO_BASE(BUTTON_RIGHT_PORT) -#define BUTTON_RIGHT_PIN_MASK GPIO_PIN_MASK(BUTTON_RIGHT_PIN) - -#define BUTTON_UP_PORT_BASE GPIO_PORT_TO_BASE(BUTTON_UP_PORT) -#define BUTTON_UP_PIN_MASK GPIO_PIN_MASK(BUTTON_UP_PIN) - -#define BUTTON_DOWN_PORT_BASE GPIO_PORT_TO_BASE(BUTTON_DOWN_PORT) -#define BUTTON_DOWN_PIN_MASK GPIO_PIN_MASK(BUTTON_DOWN_PIN) -/*---------------------------------------------------------------------------*/ -static struct timer debouncetimer; -/*---------------------------------------------------------------------------*/ -/** - * \brief Common initialiser for all buttons - * \param port_base GPIO port's register offset - * \param pin_mask Pin mask corresponding to the button's pin - */ -static void -config(uint32_t port_base, uint32_t pin_mask) -{ - /* Software controlled */ - GPIO_SOFTWARE_CONTROL(port_base, pin_mask); - - /* Set pin to input */ - GPIO_SET_INPUT(port_base, pin_mask); - - /* Enable edge detection */ - GPIO_DETECT_EDGE(port_base, pin_mask); - - /* Single edge */ - GPIO_TRIGGER_SINGLE_EDGE(port_base, pin_mask); - - /* Trigger interrupt on Falling edge */ - GPIO_DETECT_RISING(port_base, pin_mask); - - GPIO_ENABLE_INTERRUPT(port_base, pin_mask); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Callback registered with the GPIO module. Gets fired with a button - * port/pin generates an interrupt - * \param port The port number that generated the interrupt - * \param pin The pin number that generated the interrupt. This is the pin - * absolute number (i.e. 0, 1, ..., 7), not a mask - */ -static void -btn_callback(uint8_t port, uint8_t pin) -{ - if(!timer_expired(&debouncetimer)) { - return; - } - - timer_set(&debouncetimer, CLOCK_SECOND / 8); - - if((port == BUTTON_SELECT_PORT) && (pin == BUTTON_SELECT_PIN)) { - sensors_changed(&button_select_sensor); - } else if((port == BUTTON_LEFT_PORT) && (pin == BUTTON_LEFT_PIN)) { - sensors_changed(&button_left_sensor); - } else if((port == BUTTON_RIGHT_PORT) && (pin == BUTTON_RIGHT_PIN)) { - sensors_changed(&button_right_sensor); - } else if((port == BUTTON_UP_PORT) && (pin == BUTTON_UP_PIN)) { - sensors_changed(&button_up_sensor); - } else if((port == BUTTON_DOWN_PORT) && (pin == BUTTON_DOWN_PIN)) { - sensors_changed(&button_down_sensor); - } -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Init function for the select button. - * - * Parameters are ignored. They have been included because the prototype is - * dictated by the core sensor api. The return value is also not required by - * the API but otherwise ignored. - * - * \param type ignored - * \param value ignored - * \return ignored - */ -static int -config_select(int type, int value) -{ - config(BUTTON_SELECT_PORT_BASE, BUTTON_SELECT_PIN_MASK); - - ioc_set_over(BUTTON_SELECT_PORT, BUTTON_SELECT_PIN, IOC_OVERRIDE_PUE); - - NVIC_EnableIRQ(BUTTON_SELECT_VECTOR); - - gpio_register_callback(btn_callback, BUTTON_SELECT_PORT, BUTTON_SELECT_PIN); - return 1; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Init function for the left button. - * - * Parameters are ignored. They have been included because the prototype is - * dictated by the core sensor api. The return value is also not required by - * the API but otherwise ignored. - * - * \param type ignored - * \param value ignored - * \return ignored - */ -static int -config_left(int type, int value) -{ - config(BUTTON_LEFT_PORT_BASE, BUTTON_LEFT_PIN_MASK); - - ioc_set_over(BUTTON_LEFT_PORT, BUTTON_LEFT_PIN, IOC_OVERRIDE_PUE); - - NVIC_EnableIRQ(BUTTON_LEFT_VECTOR); - - gpio_register_callback(btn_callback, BUTTON_LEFT_PORT, BUTTON_LEFT_PIN); - return 1; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Init function for the right button. - * - * Parameters are ignored. They have been included because the prototype is - * dictated by the core sensor api. The return value is also not required by - * the API but otherwise ignored. - * - * \param type ignored - * \param value ignored - * \return ignored - */ -static int -config_right(int type, int value) -{ - config(BUTTON_RIGHT_PORT_BASE, BUTTON_RIGHT_PIN_MASK); - - ioc_set_over(BUTTON_RIGHT_PORT, BUTTON_RIGHT_PIN, IOC_OVERRIDE_PUE); - - NVIC_EnableIRQ(BUTTON_RIGHT_VECTOR); - - gpio_register_callback(btn_callback, BUTTON_RIGHT_PORT, BUTTON_RIGHT_PIN); - return 1; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Init function for the up button. - * - * Parameters are ignored. They have been included because the prototype is - * dictated by the core sensor api. The return value is also not required by - * the API but otherwise ignored. - * - * \param type ignored - * \param value ignored - * \return ignored - */ -static int -config_up(int type, int value) -{ - config(BUTTON_UP_PORT_BASE, BUTTON_UP_PIN_MASK); - - ioc_set_over(BUTTON_UP_PORT, BUTTON_UP_PIN, IOC_OVERRIDE_PUE); - - NVIC_EnableIRQ(BUTTON_UP_VECTOR); - - gpio_register_callback(btn_callback, BUTTON_UP_PORT, BUTTON_UP_PIN); - return 1; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Init function for the down button. - * - * Parameters are ignored. They have been included because the prototype is - * dictated by the core sensor api. The return value is also not required by - * the API but otherwise ignored. - * - * \param type ignored - * \param value ignored - * \return ignored - */ -static int -config_down(int type, int value) -{ - config(BUTTON_DOWN_PORT_BASE, BUTTON_DOWN_PIN_MASK); - - ioc_set_over(BUTTON_DOWN_PORT, BUTTON_DOWN_PIN, IOC_OVERRIDE_PUE); - - NVIC_EnableIRQ(BUTTON_DOWN_VECTOR); - - gpio_register_callback(btn_callback, BUTTON_DOWN_PORT, BUTTON_DOWN_PIN); - return 1; -} -/*---------------------------------------------------------------------------*/ -void -button_sensor_init() -{ - timer_set(&debouncetimer, 0); -} -/*---------------------------------------------------------------------------*/ -SENSORS_SENSOR(button_select_sensor, BUTTON_SENSOR, NULL, config_select, NULL); -SENSORS_SENSOR(button_left_sensor, BUTTON_SENSOR, NULL, config_left, NULL); -SENSORS_SENSOR(button_right_sensor, BUTTON_SENSOR, NULL, config_right, NULL); -SENSORS_SENSOR(button_up_sensor, BUTTON_SENSOR, NULL, config_up, NULL); -SENSORS_SENSOR(button_down_sensor, BUTTON_SENSOR, NULL, config_down, NULL); - -/** @} */ diff --git a/arch/platform/cc2538dk/dev/button-sensor.h b/arch/platform/cc2538dk/dev/button-sensor.h deleted file mode 100644 index 266770d2419ec9c6b95b66531b64cacd82e18bec..0000000000000000000000000000000000000000 --- a/arch/platform/cc2538dk/dev/button-sensor.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \addtogroup cc2538-smartrf-sensors - * @{ - * - * \defgroup cc2538dk-button-sensor cc2538dk Button Driver - * - * Driver for the SmartRF06EB buttons - * @{ - * - * \file - * Header file for the cc2538dk Button Driver - */ -#ifndef BUTTON_SENSOR_H_ -#define BUTTON_SENSOR_H_ - -#include "lib/sensors.h" -#include "dev/gpio.h" - -#define BUTTON_SENSOR "Button" - -#define button_sensor button_select_sensor -extern const struct sensors_sensor button_select_sensor; -extern const struct sensors_sensor button_left_sensor; -extern const struct sensors_sensor button_right_sensor; -extern const struct sensors_sensor button_up_sensor; -extern const struct sensors_sensor button_down_sensor; -/*---------------------------------------------------------------------------*/ -#endif /* BUTTON_SENSOR_H_ */ - -/** \brief Common initialiser for all SmartRF Buttons */ -void button_sensor_init(); - -/** - * @} - * @} - */ diff --git a/arch/platform/cc2538dk/dev/leds-arch.c b/arch/platform/cc2538dk/dev/leds-arch.c index 661f461605bfa218c21e4e559751d81f8f2ef33b..78441defc5cb10babaf18b8fe998556d63c59a47 100644 --- a/arch/platform/cc2538dk/dev/leds-arch.c +++ b/arch/platform/cc2538dk/dev/leds-arch.c @@ -1,16 +1,16 @@ /* - * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. @@ -28,45 +28,32 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * \addtogroup cc2538-smartrf - * @{ - * - * \defgroup cc2538dk-leds SmartRF06EB LED driver - * - * LED driver implementation for the TI SmartRF06EB + cc2538EM - * @{ - * - * \file - * LED driver implementation for the TI SmartRF06EB + cc2538EM - */ +/*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "reg.h" #include "dev/leds.h" -#include "dev/gpio.h" +#include "dev/gpio-hal.h" +#include "dev/gpio-hal-arch.h" -#define LEDS_GPIO_PIN_MASK LEDS_ALL -/*---------------------------------------------------------------------------*/ -void -leds_arch_init(void) -{ - GPIO_SET_OUTPUT(GPIO_C_BASE, LEDS_GPIO_PIN_MASK); -} -/*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - return GPIO_READ_PIN(GPIO_C_BASE, LEDS_GPIO_PIN_MASK); -} +#include <stdbool.h> /*---------------------------------------------------------------------------*/ -void -leds_arch_set(unsigned char leds) -{ - GPIO_WRITE_PIN(GPIO_C_BASE, LEDS_GPIO_PIN_MASK, leds); -} +const leds_t leds_arch_leds[] = { + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L1_PORT, LEDS_ARCH_L1_PIN), + .negative_logic = false + }, + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L2_PORT, LEDS_ARCH_L2_PIN), + .negative_logic = false + }, + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L3_PORT, LEDS_ARCH_L3_PIN), + .negative_logic = false + }, +#if !USB_SERIAL_CONF_ENABLE + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L4_PORT, LEDS_ARCH_L4_PIN), + .negative_logic = false + }, +#endif +}; /*---------------------------------------------------------------------------*/ - -/** - * @} - * @} - */ diff --git a/arch/platform/cc2538dk/dev/smartrf-sensors.c b/arch/platform/cc2538dk/dev/smartrf-sensors.c index 76841af3b51c4f09bf7a15f4563fe462aef17e8a..1b833e764000b504c3f5f0a3f5a230fd07bf641b 100644 --- a/arch/platform/cc2538dk/dev/smartrf-sensors.c +++ b/arch/platform/cc2538dk/dev/smartrf-sensors.c @@ -41,16 +41,13 @@ * Implementation of a generic module controlling SmartRF06EB sensors */ #include "contiki.h" -#include "dev/button-sensor.h" #include "dev/als-sensor.h" #include "dev/cc2538-sensors.h" #include <string.h> /** \brief Exports a global symbol to be used by the sensor API */ -SENSORS(&button_select_sensor, &button_left_sensor, &button_right_sensor, - &button_up_sensor, &button_down_sensor, &als_sensor, - &cc2538_temp_sensor, &vdd3_sensor); +SENSORS(&als_sensor, &cc2538_temp_sensor, &vdd3_sensor); /** * @} diff --git a/arch/platform/cc2538dk/platform.c b/arch/platform/cc2538dk/platform.c index 154651c985cc1396984df6d882fc82011b0f758a..bf945bfdd20bda060e984288dfdf34795cb7d244 100644 --- a/arch/platform/cc2538dk/platform.c +++ b/arch/platform/cc2538dk/platform.c @@ -46,14 +46,15 @@ #include "dev/adc.h" #include "dev/leds.h" #include "dev/uart.h" -#include "dev/button-sensor.h" #include "dev/serial-line.h" #include "dev/slip.h" #include "dev/cc2538-rf.h" #include "dev/udma.h" #include "dev/crypto.h" +#include "dev/button-hal.h" #include "usb/usb-serial.h" #include "lib/random.h" +#include "lib/sensors.h" #include "net/netstack.h" #include "net/mac/framer/frame802154.h" #include "net/linkaddr.h" @@ -74,7 +75,7 @@ #define LOG_LEVEL LOG_LEVEL_MAIN /*---------------------------------------------------------------------------*/ static void -fade(unsigned char l) +fade(leds_mask_t l) { volatile int i; int k, j; @@ -83,11 +84,11 @@ fade(unsigned char l) leds_on(l); for(i = 0; i < j; ++i) { - asm("nop"); + __asm("nop"); } leds_off(l); for(i = 0; i < 400 - j; ++i) { - asm("nop"); + __asm("nop"); } } } @@ -103,9 +104,6 @@ set_rf_params(void) short_addr = ext_addr[7]; short_addr |= ext_addr[6] << 8; - /* Populate linkaddr_node_addr. Maintain endianness */ - memcpy(&linkaddr_node_addr, &ext_addr[8 - LINKADDR_SIZE], LINKADDR_SIZE); - NETSTACK_RADIO.set_value(RADIO_PARAM_PAN_ID, IEEE802154_PANID); NETSTACK_RADIO.set_value(RADIO_PARAM_16BIT_ADDR, short_addr); NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, CC2538_RF_CHANNEL); @@ -124,8 +122,6 @@ platform_init_stage_one(void) void platform_init_stage_two() { - button_sensor_init(); - /* * Character I/O Initialisation. * When the UART receives a character it will call serial_line_input_byte to @@ -159,7 +155,10 @@ platform_init_stage_two() crypto_disable(); #endif - set_rf_params(); + /* Populate linkaddr_node_addr */ + ieee_addr_cpy_to(linkaddr_node_addr.u8, LINKADDR_SIZE); + + button_hal_init(); INTERRUPTS_ENABLE(); @@ -171,6 +170,8 @@ platform_init_stage_three() { LOG_INFO("%s\n", BOARD_STRING); + set_rf_params(); + soc_print_info(); adc_init(); diff --git a/arch/platform/cooja/Makefile.cooja b/arch/platform/cooja/Makefile.cooja index 9f41dbaad095d36a15ff60276fb307f3b9ac5b81..d06aa08d55f69fced65831aa182d0c81756a204a 100644 --- a/arch/platform/cooja/Makefile.cooja +++ b/arch/platform/cooja/Makefile.cooja @@ -38,10 +38,7 @@ endif ## QUICKSTART MAIN_OBJ = $(OBJECTDIR)/$(LIBNAME).o ARCHIVE = $(OBJECTDIR)/$(LIBNAME).a JNILIB = $(OBJECTDIR)/$(LIBNAME).$(TARGET) -CONTIKI_APP_OBJ = $(CONTIKI_APP).co - -# Modules -MODULES += os/net os/net/mac os/net/mac/framer +CONTIKI_APP_OBJ = $(CONTIKI_APP).o ### COOJA platform sources COOJA = $(CONTIKI)/arch/platform/$(TARGET) @@ -67,6 +64,8 @@ CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) .SUFFIXES: +CLEAN += COOJA.log + ### Define the CPU directory CONTIKI_CPU=$(CONTIKI)/arch/cpu/x86 diff --git a/arch/platform/cooja/Makefile.customrules-cooja b/arch/platform/cooja/Makefile.customrules-cooja index de35d4185a6619a0c5279a29332e312b97b6c721..42d6e125eaf4e09eaa965345a238004baa0577db 100644 --- a/arch/platform/cooja/Makefile.customrules-cooja +++ b/arch/platform/cooja/Makefile.customrules-cooja @@ -32,5 +32,5 @@ $(CONTIKI_APP).cooja: $(JNILIB) # Trickiness: GNU make matches this against the file base name. # Assume that the directory part is the standard location. -mtype%.o: contiki-cooja-main.o | $(OBJECTDIR) - mv contiki-cooja-main.o $@ +mtype%.o: platform.o | $(OBJECTDIR) + mv platform.o $@ diff --git a/arch/platform/cooja/contiki-conf.h b/arch/platform/cooja/contiki-conf.h index 638297730602d1ebf92b36fef103c5f44ceaacd4..75a37f8661e71342c139a3155a3753439acfabe1 100644 --- a/arch/platform/cooja/contiki-conf.h +++ b/arch/platform/cooja/contiki-conf.h @@ -42,10 +42,14 @@ #include "subplatform-conf.h" #endif /* INCLUDE_SUBPLATFORM_CONF */ +#define PLATFORM_CONF_PROVIDES_MAIN_LOOP 1 + #define LOG_CONF_ENABLED 1 #define COOJA 1 +#define LEDS_CONF_LEGACY_API 1 + #ifndef EEPROM_CONF_SIZE #define EEPROM_CONF_SIZE 1024 #endif @@ -87,8 +91,6 @@ #define NBR_TABLE_CONF_MAX_NEIGHBORS 300 #endif /* NBR_TABLE_CONF_MAX_NEIGHBORS */ -#define TCPIP_CONF_ANNOTATE_TRANSMISSIONS 1 - #ifndef UIP_CONF_IPV6_QUEUE_PKT #define UIP_CONF_IPV6_QUEUE_PKT 1 #endif /* UIP_CONF_IPV6_QUEUE_PKT */ @@ -100,9 +102,6 @@ #define CC_CONF_VA_ARGS 1 #define CC_CONF_INLINE inline -#define CCIF -#define CLIF - /* These names are deprecated, use C99 names. */ #include <inttypes.h> typedef uint8_t u8_t; @@ -137,4 +136,6 @@ typedef uint64_t rtimer_clock_t; #define RF_CHANNEL 26 #define NETSTACK_RADIO_MAX_PAYLOAD_LEN 125 +#define PLATFORM_CONF_SUPPORTS_STACK_CHECK 0 + #endif /* CONTIKI_CONF_H_ */ diff --git a/arch/platform/cooja/dev/leds-arch.c b/arch/platform/cooja/dev/leds-arch.c index db91e9baa53d10c1832da0d43413f3516c44722e..b65df294567e019b8bacf07b649446632e67bc94 100644 --- a/arch/platform/cooja/dev/leds-arch.c +++ b/arch/platform/cooja/dev/leds-arch.c @@ -34,18 +34,18 @@ const struct simInterface leds_interface; // COOJA variables -unsigned char simLedsValue; +leds_mask_t simLedsValue; /*-----------------------------------------------------------------------------------*/ void leds_arch_init() { simLedsValue = 0; } /*-----------------------------------------------------------------------------------*/ -unsigned char leds_arch_get() { +leds_mask_t leds_arch_get() { return simLedsValue; } /*-----------------------------------------------------------------------------------*/ -void leds_arch_set(unsigned char leds) { +void leds_arch_set(leds_mask_t leds) { if(leds != simLedsValue) { simLedsValue = leds; } diff --git a/arch/platform/cooja/doxygen-group.txt b/arch/platform/cooja/doxygen-group.txt new file mode 100644 index 0000000000000000000000000000000000000000..ce6c60b0dbbf7ec8a69d84becefa33f92d4c8b11 --- /dev/null +++ b/arch/platform/cooja/doxygen-group.txt @@ -0,0 +1,4 @@ +/** + * \defgroup cooja COOJA network simulator node + * \ingroup platform + */ diff --git a/arch/platform/cooja/contiki-cooja-main.c b/arch/platform/cooja/platform.c similarity index 77% rename from arch/platform/cooja/contiki-cooja-main.c rename to arch/platform/cooja/platform.c index 39793d12cec97e39db87b9684724e6b935ec363c..9ef310bce6b2639fc2ed6bdde4d86a273fd50f3d 100644 --- a/arch/platform/cooja/contiki-cooja-main.c +++ b/arch/platform/cooja/platform.c @@ -45,8 +45,12 @@ #include "sys/clock.h" #include "sys/etimer.h" #include "sys/cooja_mt.h" -#include "sys/autostart.h" + +/*---------------------------------------------------------------------------*/ +/* Log configuration */ #include "sys/log.h" +#define LOG_MODULE "Cooja" +#define LOG_LEVEL LOG_LEVEL_MAIN #include "lib/random.h" #include "lib/simEnvChange.h" @@ -62,6 +66,7 @@ #include "dev/vib-sensor.h" #include "sys/node-id.h" +#include "services/rpl-border-router/rpl-border-router.h" #if BUILD_WITH_ORCHESTRA #include "orchestra.h" #endif /* BUILD_WITH_ORCHESTRA */ @@ -71,7 +76,7 @@ /* JNI-defined functions, depends on the environment variable CLASSNAME */ #ifndef CLASSNAME -#error CLASSNAME is undefined, required by contiki-cooja-main.c +#error CLASSNAME is undefined, required by platform.c #endif /* CLASSNAME */ #define COOJA__QUOTEME(a,b,c) COOJA_QUOTEME(a,b,c) #define COOJA_QUOTEME(a,b,c) a##b##c @@ -82,15 +87,14 @@ #define Java_org_contikios_cooja_corecomm_CLASSNAME_tick COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_tick) #define Java_org_contikios_cooja_corecomm_CLASSNAME_setReferenceAddress COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_setReferenceAddress) -#ifndef NETSTACK_CONF_WITH_IPV6 -#define NETSTACK_CONF_WITH_IPV6 0 -#endif #if NETSTACK_CONF_WITH_IPV6 #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" -#define PRINT6ADDR(addr) printf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) #endif /* NETSTACK_CONF_WITH_IPV6 */ +/* The main function, implemented in contiki-main.c */ +int main(void); + /* Simulation mote interfaces */ SIM_INTERFACE_NAME(moteid_interface); SIM_INTERFACE_NAME(vib_interface); @@ -124,18 +128,6 @@ long referenceVar; static struct cooja_mt_thread rtimer_thread; static struct cooja_mt_thread process_run_thread; -/*---------------------------------------------------------------------------*/ -static void -print_processes(struct process * const processes[]) -{ - /* const struct process * const * p = processes;*/ - printf("Starting"); - while(*processes != NULL) { - printf(" '%s'", (*processes)->name); - processes++; - } - putchar('\n'); -} /*---------------------------------------------------------------------------*/ static void rtimer_thread_loop(void *data) @@ -168,117 +160,65 @@ set_lladdr(void) addr.u8[1] = node_id >> 8; #endif /* NETSTACK_CONF_WITH_IPV6 */ linkaddr_set_node_addr(&addr); - - printf("Link-layer address "); - log_lladdr(&addr); - printf("\n"); } /*---------------------------------------------------------------------------*/ void -contiki_init() +platform_init_stage_one() +{ + return; +} +/*---------------------------------------------------------------------------*/ +void +platform_init_stage_two() +{ + set_lladdr(); +} +/*---------------------------------------------------------------------------*/ +void +platform_init_stage_three() { - /* Initialize random generator (moved to moteid.c) */ - - /* Start process handler */ - process_init(); - - - /* Start Contiki processes */ - - process_start(&etimer_process, NULL); - process_start(&sensors_process, NULL); - ctimer_init(); - - /* Print startup information */ - printf(CONTIKI_VERSION_STRING " started. "); if(node_id > 0) { - printf("Node id is set to %u.\n", node_id); + LOG_INFO("Node id is set to %u.\n", node_id); } else { - printf("Node id is not set.\n"); + LOG_INFO("Node id is not set.\n"); } - - set_lladdr(); - { - uint8_t longaddr[8]; - - memset(longaddr, 0, sizeof(longaddr)); - linkaddr_copy((linkaddr_t *)&longaddr, &linkaddr_node_addr); - printf("MAC %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ", - longaddr[0], longaddr[1], longaddr[2], longaddr[3], - longaddr[4], longaddr[5], longaddr[6], longaddr[7]); - } - - /* Initialize communication stack */ - netstack_init(); - printf("%s/%s\n", - NETSTACK_NETWORK.name, NETSTACK_MAC.name); - -#if NETSTACK_CONF_WITH_IPV6 - /* IPv6 CONFIGURATION */ - { - int i; - uip_ds6_addr_t *lladdr; - uint8_t addr[sizeof(uip_lladdr.addr)]; - for(i = 0; i < sizeof(uip_lladdr.addr); i += 2) { - addr[i + 1] = node_id & 0xff; - addr[i + 0] = node_id >> 8; - } - linkaddr_copy((linkaddr_t *)addr, &linkaddr_node_addr); - memcpy(&uip_lladdr.addr, addr, sizeof(uip_lladdr.addr)); - - process_start(&tcpip_process, NULL); - - lladdr = uip_ds6_get_link_local(-1); - printf("Tentative link-local IPv6 address "); - log_6addr(lladdr != NULL ? &lladdr->ipaddr : NULL); - printf("\n"); - } -#endif /* NETSTACK_CONF_WITH_IPV6 */ - /* Initialize eeprom */ eeprom_init(); - /* Start serial process */ serial_line_init(); +} +/*---------------------------------------------------------------------------*/ +void +platform_main_loop() +{ + while(1) + { + simProcessRunValue = process_run(); + while(simProcessRunValue-- > 0) { + process_run(); + } + simProcessRunValue = process_nevents(); -#if BUILD_WITH_ORCHESTRA - orchestra_init(); -#endif /* BUILD_WITH_ORCHESTRA */ -#if BUILD_WITH_SHELL - serial_shell_init(); -#endif /* BUILD_WITH_SHELL */ + /* Check if we must stay awake */ + if(simDontFallAsleep) { + simDontFallAsleep = 0; + simProcessRunValue = 1; + } - /* Start autostart processes (defined in Contiki application) */ - print_processes(autostart_processes); - autostart_start(autostart_processes); + /* Return to COOJA */ + cooja_mt_yield(); + } } /*---------------------------------------------------------------------------*/ static void process_run_thread_loop(void *data) { - /* Yield once during bootup */ - simProcessRunValue = 1; - cooja_mt_yield(); - - contiki_init(); + /* Yield once during bootup */ + simProcessRunValue = 1; + cooja_mt_yield(); - while(1) - { - simProcessRunValue = process_run(); - while(simProcessRunValue-- > 0) { - process_run(); - } - simProcessRunValue = process_nevents(); - - /* Check if we must stay awake */ - if(simDontFallAsleep) { - simDontFallAsleep=0; - simProcessRunValue = 1; - } - - /* Return to COOJA */ - cooja_mt_yield(); - } + /* Then call common Contiki-NG main function */ + main(); } /*---------------------------------------------------------------------------*/ /** diff --git a/arch/platform/cooja/sys/cooja-log.c b/arch/platform/cooja/sys/cooja-log.c index 32b0643353ccfc1794f756e2588c7edac552a9e4..c7ffdb9ac5b175daea944891fed08497528d21cf 100644 --- a/arch/platform/cooja/sys/cooja-log.c +++ b/arch/platform/cooja/sys/cooja-log.c @@ -35,10 +35,9 @@ #define IMPLEMENT_PRINTF 1 -#if MAX_LOG_LENGTH < 1024 -#undef MAX_LOG_LENGTH -#define MAX_LOG_LENGTH 1024 -#endif /* MAX_LOG_LENGTH < 1024 */ +#ifndef MAX_LOG_LENGTH +#define MAX_LOG_LENGTH 8192 +#endif /* MAX_LOG_LENGTH */ const struct simInterface simlog_interface; diff --git a/arch/platform/cooja/sys/cooja_mt.c b/arch/platform/cooja/sys/cooja_mt.c index 3ccc5c169ae7de324e4f2a4de25c18af6bf282d3..ca0d793034758811664deb46ba53044366ee76ac 100644 --- a/arch/platform/cooja/sys/cooja_mt.c +++ b/arch/platform/cooja/sys/cooja_mt.c @@ -46,18 +46,6 @@ static struct cooja_mt_thread *current; -/*--------------------------------------------------------------------------*/ -void -cooja_mt_init(void) -{ - cooja_mtarch_init(); -} -/*--------------------------------------------------------------------------*/ -void -cooja_mt_remove(void) -{ - cooja_mtarch_remove(); -} /*--------------------------------------------------------------------------*/ void cooja_mt_start(struct cooja_mt_thread *thread, void (* function)(void *), void *data) @@ -82,14 +70,6 @@ cooja_mt_exec(struct cooja_mt_thread *thread) } /*--------------------------------------------------------------------------*/ void -cooja_mt_exit(void) -{ - current->state = MT_STATE_EXITED; - current = NULL; - cooja_mtarch_yield(); -} -/*--------------------------------------------------------------------------*/ -void cooja_mt_yield(void) { current->state = MT_STATE_READY; diff --git a/arch/platform/cooja/sys/cooja_mt.h b/arch/platform/cooja/sys/cooja_mt.h index 4707b1fff56d5fc18f47e23601680f8073f9d029..f9138c6dd25d8157d56d0001494145fc1ee91f89 100644 --- a/arch/platform/cooja/sys/cooja_mt.h +++ b/arch/platform/cooja/sys/cooja_mt.h @@ -49,25 +49,6 @@ */ struct cooja_mtarch_thread; -/** - * Initialize the architecture specific support functions for the - * multi-thread library. - * - * This function is implemented by the architecture specific functions - * for the multi-thread library and is called by the mt_init() - * function as part of the initialization of the library. The - * mtarch_init() function can be used for, e.g., starting preemtion - * timers or other architecture specific mechanisms required for the - * operation of the library. - */ -void cooja_mtarch_init(void); - -/** - * Uninstall library and clean up. - * - */ -void cooja_mtarch_remove(void); - /** * Setup the stack frame for a thread that is being started. * @@ -128,19 +109,6 @@ struct cooja_mt_thread { */ #define MT_OK 1 -/** - * Initializes the multithreading library. - * - */ -void cooja_mt_init(void); - -/** - * Uninstalls library and cleans up. - * - */ -void cooja_mt_remove(void); - - /** * Starts a multithreading thread. * @@ -201,51 +169,6 @@ void cooja_mt_exec(struct cooja_mt_thread *thread); */ void cooja_mt_yield(void); -/** - * Post an event to another process. - * - * This function is called by a running thread and will emit a signal - * to another Contiki process. This will cause the currently executing - * thread to yield. - * - * \param p The process receiving the signal, or PROCESS_BROADCAST - * for a broadcast event. - * - * \param ev The event to be posted. - * - * \param data A pointer to a message that is to be delivered together - * with the signal. - * - */ -/*void mt_post(struct process *p, process_event_t ev, process_data_t data);*/ - -/** - * Block and wait for an event to occur. - * - * This function can be called by a running thread in order to block - * and wait for an event. The function returns when an event has - * occured. The event number and the associated data are placed in the - * variables pointed to by the function arguments. - * - * \param ev A pointer to a process_event_t variable. The variable - * will be filled with the number event that woke the thread. - * - * \param data A pointer to a process_data_t variable. The variable - * will be filled with the data associated with the event that woke - * the thread. - * - */ -/*void mt_wait(process_event_t *ev, process_data_t *data);*/ - -/** - * Exit a thread. - * - * This function is called from within an executing thread in order to - * exit the thread. The function never returns. - * - */ -void cooja_mt_exit(void); - /** @} */ /** @} */ #endif /* MT_H_ */ diff --git a/arch/platform/cooja/sys/cooja_mtarch.c b/arch/platform/cooja/sys/cooja_mtarch.c index 8d73ad0882affffaca495d7c21249bb83d28112a..4a1f783600211e10c199b33dbcc94e03c141d2c5 100644 --- a/arch/platform/cooja/sys/cooja_mtarch.c +++ b/arch/platform/cooja/sys/cooja_mtarch.c @@ -72,11 +72,7 @@ struct frame { unsigned long retaddr2; unsigned long data; }; -/*--------------------------------------------------------------------------*/ -void -cooja_mtarch_init(void) -{ -} + /*--------------------------------------------------------------------------*/ void cooja_mtarch_start(struct cooja_mtarch_thread *t, @@ -187,35 +183,8 @@ cooja_mtarch_exec(struct cooja_mtarch_thread *t) } /*--------------------------------------------------------------------------*/ void -cooja_mtarch_remove(void) -{ -} -/*--------------------------------------------------------------------------*/ -void cooja_mtarch_yield(void) { cooja_sw(); } /*--------------------------------------------------------------------------*/ -void -cooja_mtarch_pstop(void) -{ -} -/*--------------------------------------------------------------------------*/ -void -cooja_mtarch_pstart(void) -{ -} -/*--------------------------------------------------------------------------*/ -int -cooja_mtarch_stack_usage(struct cooja_mt_thread *t) -{ - int i; - for(i = 0; i < COOJA_MTARCH_STACKSIZE; ++i) { - if(t->thread.stack[i] != i) { - return COOJA_MTARCH_STACKSIZE - i; - } - } - return -1; -} -/*--------------------------------------------------------------------------*/ diff --git a/arch/platform/cooja/sys/cooja_mtarch.h b/arch/platform/cooja/sys/cooja_mtarch.h index 084962e81286dd9e70833e3ed22026a4080c4004..2a16c0ae4000323fda2f693b37d907c85c434db8 100644 --- a/arch/platform/cooja/sys/cooja_mtarch.h +++ b/arch/platform/cooja/sys/cooja_mtarch.h @@ -46,7 +46,4 @@ struct cooja_mtarch_thread { struct cooja_mt_thread; -int cooja_mtarch_stack_usage(struct cooja_mt_thread *t); - #endif /* COOJA_MTARCH_H_ */ - diff --git a/arch/platform/jn516x/Makefile.jn516x b/arch/platform/jn516x/Makefile.jn516x index bf1560e31809a34dfd8341a8b71c891262cebf3d..9f7a31adfaccbfe031daa2756fb29b3d7e75bd81 100644 --- a/arch/platform/jn516x/Makefile.jn516x +++ b/arch/platform/jn516x/Makefile.jn516x @@ -81,8 +81,8 @@ OBJCOPY:=$(CROSS_COMPILE)-objcopy OBJDUMP:=$(CROSS_COMPILE)-objdump ARCH = jn516x-ccm-star.c exceptions.c rtimer-arch.c rtimer-arch-slow.c \ - slip_uart0.c clock.c micromac-radio.c \ - mtarch.c node-id.c watchdog.c slip.c sprintf.c + slip_uart0.c clock.c micromac-radio.c int-master.c \ + node-id.c watchdog.c slip.c dbg.c # Default uart0 for printf and slip TARGET_WITH_UART0 ?= 1 TARGET_WITH_UART1 ?= 0 @@ -100,9 +100,11 @@ ifeq ($(WITH_UART),1) ARCH += uart-driver.c endif -CONTIKI_TARGET_DIRS = . dev lib +CONTIKI_TARGET_DIRS = . dev CONTIKI_TARGET_MAIN = platform.c +MODULES += os/lib/dbg-io + ifeq ($(JN516x_WITH_DR1175),1) JN516x_WITH_DR1174 = 1 CFLAGS += -DSENSOR_BOARD_DR1175 @@ -140,11 +142,8 @@ ifdef nodemac CFLAGS += -DMACID=$(nodemac) endif -CLEAN += *.jn516x CLEAN += *.jn516x.bin -MODULES += os/net os/net/mac os/net/mac/framer - CONTIKI_TARGET_SOURCEFILES += $(ARCH) CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) @@ -164,6 +163,10 @@ CFLAGS := $(patsubst -I/cygdrive/c/%,-Ic:/%,$(CFLAGS)) LDFLAGS := $(patsubst -L/cygdrive/c/%,-Lc:/%,$(LDFLAGS)) endif +# These symbols are used by the stack check library +LDFLAGS += -Wl,--defsym=_stack=_stack_low_water_mark +LDFLAGS += -Wl,--defsym=_stack_origin=_ram_top + ######################################################################## MOTELIST = python $(CONTIKI)/tools/jn516x/mote-list.py @@ -232,16 +235,16 @@ ABS_APPLIBS = $(addsuffix _$(JENNIC_CHIP_FAMILY).a,$(addprefix $(COMPONENTS_BASE ifneq ($(wildcard $(SDK_BASE_DIR)/Components/Library/*),) # The SDK is fully installed, proceed to linking and objcopy to ready-to-upload .jn516x.bin file -%.$(TARGET): %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(ABS_APPLIBS) +%.$(TARGET): %.o $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) $(CONTIKI_NG_TARGET_LIB) $(ABS_APPLIBS) echo ${filter %.a,$^} $(Q)$(CC) -Wl,--gc-sections $(LDFLAGS) -T$(LINKCMD) -o $@ -Wl,--start-group \ $(patsubst /cygdrive/c/%,c:/%,${filter-out %.a,$^}) \ $(patsubst /cygdrive/c/%,c:/%,${filter %.a,$^}) \ - $(ALLLIBS) -Wl,--end-group -Wl,-Map,contiki-$(TARGET).map + $(ALLLIBS) -Wl,--end-group -Wl,-Map,$(CONTIKI_NG_PROJECT_MAP) $(OBJCOPY) -S -O binary $@ $@.bin else # The SDK does not include libraries, only build objects and libraries, skip linking -%.$(TARGET): %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a +%.$(TARGET): %.o $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) $(CONTIKI_NG_TARGET_LIB) echo Creating empty $@ touch $@ endif diff --git a/arch/platform/jn516x/contiki-conf.h b/arch/platform/jn516x/contiki-conf.h index 620e5567493357fa939ed46a0f6ffe474ee81074..f8dbdc3e53258b430df31dc7df6dc3ed755a3342 100644 --- a/arch/platform/jn516x/contiki-conf.h +++ b/arch/platform/jn516x/contiki-conf.h @@ -38,11 +38,15 @@ #include PROJECT_CONF_PATH #endif /* PROJECT_CONF_PATH */ -#ifdef PLATFORM_CONF_H -#include PLATFORM_CONF_H -#else -#include "platform-conf.h" -#endif /* PLATFORM_CONF_H */ +#include "jn516x-def.h" + +#ifdef RF_CHANNEL +#define MICROMAC_CONF_CHANNEL RF_CHANNEL +#endif + +#ifndef MICROMAC_CONF_CHANNEL +#define MICROMAC_CONF_CHANNEL 26 +#endif /* Configure radio driver */ #ifndef NETSTACK_CONF_RADIO diff --git a/arch/platform/nrf52dk/dbg-io/debug-uart.h b/arch/platform/jn516x/dbg.c similarity index 82% rename from arch/platform/nrf52dk/dbg-io/debug-uart.h rename to arch/platform/jn516x/dbg.c index b52d2fb50e728c501fdf430f56db4779f9cc18c3..ac6cc3888916d22c1a63a18d1bce2398e123f70d 100644 --- a/arch/platform/nrf52dk/dbg-io/debug-uart.h +++ b/arch/platform/jn516x/dbg.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Nordic Semiconductor + * Copyright (c) 2014, SICS Swedish ICT. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,30 +25,32 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - */ -/** - * \addtogroup nrf52dk - * @{ - * - * \addtogroup nrf52dk-dbg-io Debug IO over UART - * @{ - * - * \file - * A header file to maintain compatibility with DBG I/O. - * \author - * Wojciech Bober <wojciech.bober@nordicsemi.no> - * */ /*---------------------------------------------------------------------------*/ -#ifndef DEBUG_UART_H_ -#define DEBUG_UART_H_ +#include "contiki.h" + +#include <MicroInt.h> +#include "dev/uart0.h" /*---------------------------------------------------------------------------*/ -#include "dbg.h" +int +dbg_putchar(int c) +{ + uart0_writeb(c); + return 1; +} /*---------------------------------------------------------------------------*/ -#endif /* DEBUG_UART_H_ */ +unsigned int +dbg_send_bytes(const unsigned char *s, unsigned int len) +{ + unsigned int i = 0; + + while(s && *s != 0) { + if(i >= len) { + break; + } + uart0_writeb(*s++); + i++; + } + return i; +} /*---------------------------------------------------------------------------*/ -/** - * @} - * @} - */ diff --git a/arch/platform/jn516x/dev/dongle/leds-arch.c b/arch/platform/jn516x/dev/dongle/leds-arch.c index 5eff3c63e872d8ea18a02ba31c6e24cda06fc9bc..513d52b76a24490f1e018a2e11e107c342506d48 100644 --- a/arch/platform/jn516x/dev/dongle/leds-arch.c +++ b/arch/platform/jn516x/dev/dongle/leds-arch.c @@ -38,7 +38,7 @@ #define LED_G (1 << 16) #define LED_R (1 << 17) -static volatile uint8_t leds; +static volatile leds_mask_t leds; /*---------------------------------------------------------------------------*/ void @@ -49,14 +49,14 @@ leds_arch_init(void) leds = 0; } /*---------------------------------------------------------------------------*/ -unsigned char +leds_mask_t leds_arch_get(void) { return leds; } /*---------------------------------------------------------------------------*/ void -leds_arch_set(unsigned char c) +leds_arch_set(leds_mask_t c) { uint32 on_mask = 0; uint32 off_mask = 0; diff --git a/arch/platform/jn516x/dev/dr1174/README.md b/arch/platform/jn516x/dev/dr1174/README.md index d3a21cbe03233fec372bcbe7fc78c101cfc82dd2..60bffde144225a35031c6aaea1511747831619b8 100644 --- a/arch/platform/jn516x/dev/dr1174/README.md +++ b/arch/platform/jn516x/dev/dr1174/README.md @@ -5,4 +5,4 @@ Mapping of LEDs on JN516x DR1174: leds.h: led on DR1174: LEDS_GP0 LED D3 LEDS_GP1 LED D6 -Note: LEDS_GPx definitions included in leds.h via platform-conf.h +Note: LEDS_GPx definitions included in leds.h via jn516x-def.h diff --git a/arch/platform/jn516x/dev/dr1175/README.md b/arch/platform/jn516x/dev/dr1175/README.md index bf57a0a0ec04d49963bc57e1ae6b1c28e4e055fd..e4fe60adf67e75f6a37977357e89f6c0f4517b6c 100644 --- a/arch/platform/jn516x/dev/dr1175/README.md +++ b/arch/platform/jn516x/dev/dr1175/README.md @@ -14,4 +14,4 @@ DR1174+DR1175: LEDS_WHITE White power led with level control on DR1175 LEDS_GP0 LEDS D3 on DR1174 LEDS_GP1 LEDS D6 on DR1174 -Note: LEDS_GPx and LEDS_WHITE definitions included in leds.h via platform-conf.h +Note: LEDS_GPx and LEDS_WHITE definitions included in leds.h via jn516x-def.h diff --git a/arch/platform/jn516x/dev/dr1199/README.md b/arch/platform/jn516x/dev/dr1199/README.md index 83404a83b749318429d267a9e58d868ca213dabe..c6e622652ef34005d0b324849220fde99be22a5d 100644 --- a/arch/platform/jn516x/dev/dr1199/README.md +++ b/arch/platform/jn516x/dev/dr1199/README.md @@ -16,4 +16,4 @@ DR1174+DR1199: LEDS_RED LED D3 on DR1199 LEDS_GP0 LED D3 on DR1174 LEDS_GP1 LED D6 on DR1174 -Note: LEDS_GPx definitions included in leds.h via platform-conf.h +Note: LEDS_GPx definitions included in leds.h via jn516x-def.h diff --git a/arch/platform/jn516x/dev/micromac-radio.c b/arch/platform/jn516x/dev/micromac-radio.c index c3117c6f8e323af96f4bc91568e69e21590f4ffe..3ebc1357832a24d7b808e1b4dd88cb6f677bf3da 100644 --- a/arch/platform/jn516x/dev/micromac-radio.c +++ b/arch/platform/jn516x/dev/micromac-radio.c @@ -278,8 +278,7 @@ init(void) vMMAC_EnableInterrupts(&radio_interrupt_handler); } vMMAC_ConfigureRadio(); - set_channel(current_channel); - set_txpower(current_tx_power); + set_txpower(current_tx_power); /* it sets also the current_channel */ vMMAC_GetMacAddress(&node_long_address); /* Short addresses are disabled by default */ @@ -493,8 +492,7 @@ void set_channel(int c) { current_channel = c; - /* will fine tune TX power as well */ - vMMAC_SetChannel(current_channel); + vMMAC_SetChannelAndPower(current_channel, current_tx_power); } /*---------------------------------------------------------------------------*/ #if !MICROMAC_RADIO_MAC diff --git a/arch/platform/jn516x/dev/mtarch.c b/arch/platform/jn516x/dev/mtarch.c deleted file mode 100644 index c3c81457eedb26acd3e7a9d0d6cbb09f4f8437a9..0000000000000000000000000000000000000000 --- a/arch/platform/jn516x/dev/mtarch.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2008 - * Telecooperation Office (TecO), Universitaet Karlsruhe (TH), Germany. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * 3. Neither the name of the Universitaet Karlsruhe (TH) nor the names - * of its contributors may be used to endorse or promote products - * derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author(s): Philipp Scholl <scholl@teco.edu> - */ - -/* Copied from Philipp Scholl's (BSD) Contiki port to Jennic */ - -#include "mtarch.h" - -void -mtarch_init(void) -{ -} -void -mtarch_remove(void) -{ -} -void -mtarch_start(struct mtarch_thread *thread, - void (*function)(void *data), - void *data) -{ -} -void -mtarch_yield(void) -{ -} -void -mtarch_exec(struct mtarch_thread *thread) -{ -} -void -mtarch_stop(struct mtarch_thread *thread) -{ -} -void -mtarch_pstart(void) -{ -} -void -mtarch_pstop(void) -{ -} diff --git a/arch/platform/jn516x/dev/mtarch.h b/arch/platform/jn516x/dev/mtarch.h deleted file mode 100644 index 3c6292f1d6866462f2f793964a39e00b2d15c3d7..0000000000000000000000000000000000000000 --- a/arch/platform/jn516x/dev/mtarch.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2008 - * Telecooperation Office (TecO), Universitaet Karlsruhe (TH), Germany. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * 3. Neither the name of the Universitaet Karlsruhe (TH) nor the names - * of its contributors may be used to endorse or promote products - * derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author(s): Philipp Scholl <scholl@teco.edu> - */ - -/* Copied from Philipp Scholl's (BSD) Contiki port to Jennic */ - -#ifndef __MTARCH_H__ -#define __MTARCH_H__ - -struct mtarch_thread { - void *mt_thread; -}; - -#endif /* __MTARCH_H__ */ diff --git a/arch/platform/jn516x/doxygen-group.txt b/arch/platform/jn516x/doxygen-group.txt new file mode 100644 index 0000000000000000000000000000000000000000..11e5a702c35a40b278fb067382f202d976d6dc77 --- /dev/null +++ b/arch/platform/jn516x/doxygen-group.txt @@ -0,0 +1,4 @@ +/** + * \defgroup jn516x The JN516x Board + * \ingroup platform + */ diff --git a/arch/platform/jn516x/int-master.c b/arch/platform/jn516x/int-master.c new file mode 100644 index 0000000000000000000000000000000000000000..d86bd801b1ea49e28e93a84752cad9f65f0b2865 --- /dev/null +++ b/arch/platform/jn516x/int-master.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \file + * Master interrupt manipulation implementation for the JN516x + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "MicroSpecific.h" +#include "sys/int-master.h" + +#include <stdbool.h> +/*---------------------------------------------------------------------------*/ +void +int_master_enable(void) +{ + MICRO_ENABLE_INTERRUPTS(); +} +/*---------------------------------------------------------------------------*/ +int_master_status_t +int_master_read_and_disable(void) +{ + int_master_status_t status; + + MICRO_DISABLE_AND_SAVE_INTERRUPTS(status); + + return status; +} +/*---------------------------------------------------------------------------*/ +void +int_master_status_set(int_master_status_t status) +{ + MICRO_RESTORE_INTERRUPTS(status); +} +/*---------------------------------------------------------------------------*/ +bool +int_master_is_enabled(void) +{ + int_master_status_t status; + + asm volatile ("bw.mfspr %0, r0, 17;" :"=r"(status) : ); + + return status; +} +/*---------------------------------------------------------------------------*/ diff --git a/arch/platform/jn516x/platform-conf.h b/arch/platform/jn516x/jn516x-def.h similarity index 96% rename from arch/platform/jn516x/platform-conf.h rename to arch/platform/jn516x/jn516x-def.h index 990512ac22bdfeb58379579467de14095e948a07..0c76a4332c8a1794b3be6c9e0b3eaad13ceb6e7f 100644 --- a/arch/platform/jn516x/platform-conf.h +++ b/arch/platform/jn516x/jn516x-def.h @@ -30,8 +30,8 @@ * */ -#ifndef PLATFORM_CONF_H -#define PLATFORM_CONF_H +#ifndef JN516X_DEF_H_ +#define JN516X_DEF_H_ #include <inttypes.h> #include <jendefs.h> @@ -56,14 +56,6 @@ #define MIRCOMAC_CONF_BUF_NUM 2 #endif -#ifdef RF_CHANNEL -#define MICROMAC_CONF_CHANNEL RF_CHANNEL -#endif - -#ifndef MICROMAC_CONF_CHANNEL -#define MICROMAC_CONF_CHANNEL 26 -#endif - /* 32kHz or 16MHz rtimers? */ #ifdef RTIMER_CONF_USE_32KHZ #define RTIMER_USE_32KHZ RTIMER_CONF_USE_32KHZ @@ -204,6 +196,8 @@ typedef uint32_t rtimer_clock_t; #define PLATFORM_HAS_SHT11 0 #define PLATFORM_HAS_RADIO 1 +#define LEDS_CONF_LEGACY_API 1 + #define PLATFORM_CONF_PROVIDES_MAIN_LOOP 1 /* CPU target speed in Hz @@ -225,9 +219,6 @@ typedef uint32_t rtimer_clock_t; #define CC_CONF_VA_ARGS 1 #define CC_CONF_INLINE inline -#define CCIF -#define CLIF - #ifdef HAVE_STDINT_H #include <stdint.h> #else @@ -278,11 +269,6 @@ typedef uint32_t clock_time_t; #endif #define ENABLE_ADVANCED_BAUD_SELECTION (UART_BAUD_RATE > UART_RATE_115200) -/* Set this to zero only if we are using SLIP */ -#ifndef SLIP_BRIDGE_CONF_NO_PUTCHAR -#define SLIP_BRIDGE_CONF_NO_PUTCHAR 1 -#endif /* SLIP_BRIDGE_CONF_NO_PUTCHAR */ - /* Extension of LED definitions from leds.h for various JN516x dev boards JN516x Dongle: LEDS_RED Red LED on dongle @@ -314,4 +300,5 @@ DR1174+DR1175: #define LEDS_GP2 64 #define LEDS_GP3 128 #define LEDS_CONF_ALL 255 -#endif /* PLATFORM_CONF_H */ + +#endif /* JN516X_DEF_H_ */ diff --git a/arch/platform/jn516x/lib/sprintf.c b/arch/platform/jn516x/lib/sprintf.c deleted file mode 100644 index dd2408090cff23f91d9006ebdca82fe5add26dfb..0000000000000000000000000000000000000000 --- a/arch/platform/jn516x/lib/sprintf.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - File: printf.c - - Copyright (c) 2004,2008 Kustaa Nyholm / SpareTimeLabs - - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, this list - of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or other - materials provided with the distribution. - - Neither the name of the Kustaa Nyholm or SpareTimeLabs nor the names of its - contributors may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - OF SUCH DAMAGE. - - */ - -/* - * This is BSD code obtained from http://www.sparetimelabs.com/printfrevisited/index.html - * From the web page: - * "The code is GPL and BSD lincensed, download the BSD licensed version from the link - * above or use the GPL licensed code from this page below." - * - * modified by Beshr Al Nahas <beshr@sics.se> and Simon Duquennoy <simonduq@sics.se> - */ - -#include "contiki.h" -#include <stdarg.h> -#include <ctype.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include "dev/uart0.h" - -static char *bf, buf[14], uc, zs; -static unsigned int num; - -static void -out(char c) -{ - *bf++ = c; -} -static void -outDgt(char dgt) -{ - out(dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10)); - zs = 1; -} -static void -divOut(unsigned int div) -{ - unsigned char dgt = 0; - while(num >= div) { - num -= div; - dgt++; - } - if(zs || dgt > 0) { - outDgt(dgt); - } -} -int -vsnprintf(char *str, size_t n, const char *fmt, __VALIST va) -{ - char ch, *p, *str_orig = str; - char next_ch; - - while((ch = *fmt++) && str - str_orig < n) { - if(ch != '%') { - *str++ = ch; - } else { - char lz = 0; - char w = 0; - ch = *(fmt++); - if(ch == '0') { - ch = *(fmt++); - lz = 1; - } - if(ch == '-' || (ch >= '0' && ch <= '9')) { - w = 0; - while(ch == '-' || (ch >= '0' && ch <= '9')) { - if(ch != '-') { - w = (((w << 2) + w) << 1) + ch - '0'; - } - ch = *fmt++; - } - } - bf = buf; - p = bf; - zs = 0; -start_format: - next_ch = *fmt; - switch(ch) { - case 0: - goto abort; - case 'l': - if(next_ch == 'x' - || next_ch == 'X' - || next_ch == 'u' - || next_ch == 'd') { - ch = *(fmt++); - goto start_format; - } - case 'u': - case 'd': - num = va_arg(va, unsigned int); - if(ch == 'd' && (int)num < 0) { - num = -(int)num; - out('-'); - } - divOut(1000000000); - divOut(100000000); - divOut(10000000); - divOut(1000000); - divOut(100000); - divOut(10000); - divOut(1000); - divOut(100); - divOut(10); - outDgt(num); - break; - case 'p': - case 'x': - case 'X': - uc = ch == 'X'; - num = va_arg(va, unsigned int); - /* divOut(0x100000000UL); */ - divOut(0x10000000); - divOut(0x1000000); - divOut(0x100000); - divOut(0x10000); - divOut(0x1000); - divOut(0x100); - divOut(0x10); - outDgt(num); - break; - case 'c': - out((char)(va_arg(va, int))); - break; - case 's': - p = va_arg(va, char *); - break; - case '%': - out('%'); - default: - break; - } - *bf = 0; - bf = p; - - while(*bf++ && w > 0) { - w--; - } - while(w-- > 0) { - if(str - str_orig < n) { - *str++ = lz ? '0' : ' '; - } else { - goto abort; - } - } - while((ch = *p++)) { - if(str - str_orig < n) { - *str++ = ch; - } else { - goto abort; - } - } - } - } - -abort: - if(str - str_orig < n) { - *str = '\0'; - } else { - *(--str) = '\0'; - } return str - str_orig; -} -int -sprintf(char *str, const char *fmt, ...) -{ - int m; - __VALIST va; - va_start(va, fmt); - m = vsnprintf(str, 0xffffffff, fmt, va); - va_end(va); - return m; -} -int -snprintf(char *str, size_t n, const char *fmt, ...) -{ - int m; - __VALIST va; - va_start(va, fmt); - m = vsnprintf(str, n, fmt, va); - va_end(va); - return m; -} -int -printf(const char *fmt, ...) -{ - int m, i; - char str[256]; - __VALIST va; - va_start(va, fmt); - m = vsnprintf(str, sizeof(str), fmt, va); - va_end(va); - for(i = 0; i < m; i++) { - putchar(str[i]); - } - return m; -} -int -puts(const char *s) -{ - char c; - while((c = *s++) != '\0') { - putchar(c); - } - putchar('\n'); - return strlen(s); -} diff --git a/arch/platform/jn516x/lib/slip.c b/arch/platform/jn516x/slip.c similarity index 98% rename from arch/platform/jn516x/lib/slip.c rename to arch/platform/jn516x/slip.c index 8e66c5f669662e98e3ffce8b0bf4a3a5fedab717..173a14d60ae3ecb1d2083f0bd2088537dcfd2e0d 100644 --- a/arch/platform/jn516x/lib/slip.c +++ b/arch/platform/jn516x/slip.c @@ -167,7 +167,7 @@ slip_write_char(uint8_t c) slip_arch_writeb(c); } /*---------------------------------------------------------------------------*/ -uint8_t +void slip_write(const void *_ptr, int len) { const uint8_t *ptr = _ptr; @@ -181,14 +181,12 @@ slip_write(const void *_ptr, int len) slip_write_char(c); } slip_arch_writeb(SLIP_END); - - return len; } /*---------------------------------------------------------------------------*/ /* slip_send: forward (IPv4) packets with {UIP_FW_NETIF(..., slip_send)} * was used in slip-bridge.c */ -uint8_t +void slip_send(void) { uint16_t i; @@ -203,8 +201,6 @@ slip_send(void) slip_write_char(c); } slip_arch_writeb(SLIP_END); - - return UIP_FW_OK; } /*---------------------------------------------------------------------------*/ static void @@ -433,11 +429,3 @@ slip_input_byte(unsigned char c) return error_return_code; } /*---------------------------------------------------------------------------*/ -#if SLIP_BRIDGE_CONF_NO_PUTCHAR -int -putchar(int c) -{ - uart0_writeb(c); - return 1; -} -#endif diff --git a/arch/platform/native/Makefile.native b/arch/platform/native/Makefile.native index e94e972e578599ba7de184386591ba80c50cfffe..afeddd22f3150c1310e9ce5506d61dd23e9860b4 100644 --- a/arch/platform/native/Makefile.native +++ b/arch/platform/native/Makefile.native @@ -2,16 +2,12 @@ ifndef CONTIKI $(error CONTIKI not defined! You must specify where CONTIKI resides!) endif -ifeq ($(HOST_OS),Darwin) - AROPTS = rc -endif CONTIKI_TARGET_DIRS = . dev CONTIKI_TARGET_MAIN = ${addprefix $(OBJECTDIR)/,contiki-main.o} -CONTIKI_TARGET_SOURCEFILES = platform.c clock.c leds.c leds-arch.c \ - button-sensor.c pir-sensor.c vib-sensor.c xmem.c \ - sensors.c irq.c cfs-posix.c cfs-posix-dir.c +CONTIKI_TARGET_SOURCEFILES += platform.c clock.c xmem.c +CONTIKI_TARGET_SOURCEFILES += cfs-posix.c cfs-posix-dir.c buttons.c ifeq ($(HOST_OS),Windows) CONTIKI_TARGET_SOURCEFILES += wpcap-drv.c wpcap.c @@ -20,6 +16,10 @@ else CONTIKI_TARGET_SOURCEFILES += tun6-net.c endif +ifeq ($(HOST_OS),Linux) +TARGET_LIBFILES += -lrt +endif + CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) .SUFFIXES: @@ -30,5 +30,3 @@ MAKE_MAC ?= MAKE_MAC_NULLMAC ### Define the CPU directory CONTIKI_CPU=$(CONTIKI)/arch/cpu/native include $(CONTIKI)/arch/cpu/native/Makefile.native - -MODULES+=os/net os/net/mac os/net/mac/framer diff --git a/arch/platform/native/clock.c b/arch/platform/native/clock.c index 67d9ee3178243ef717541ee8596b05ffc8aa2a5a..3b94f3d4fbcaffce740c45404905d4b01459f848 100644 --- a/arch/platform/native/clock.c +++ b/arch/platform/native/clock.c @@ -42,24 +42,49 @@ #include <sys/time.h> /*---------------------------------------------------------------------------*/ -clock_time_t -clock_time(void) +typedef struct clock_timespec_s { + time_t tv_sec; + long tv_nsec; +} clock_timespec_t; +/*---------------------------------------------------------------------------*/ +static void +get_time(clock_timespec_t *spec) { +#if defined(__linux__) || (defined(__MACH__) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + + spec->tv_sec = ts.tv_sec; + spec->tv_nsec = ts.tv_nsec; +#else struct timeval tv; gettimeofday(&tv, NULL); - return tv.tv_sec * 1000 + tv.tv_usec / 1000; + spec->tv_sec = tv.tv_sec; + spec->tv_nsec = tv.tv_usec * 1000; +#endif +} +/*---------------------------------------------------------------------------*/ +clock_time_t +clock_time(void) +{ + clock_timespec_t ts; + + get_time(&ts); + + return ts.tv_sec * CLOCK_SECOND + ts.tv_nsec / (1000000000 / CLOCK_SECOND); } /*---------------------------------------------------------------------------*/ unsigned long clock_seconds(void) { - struct timeval tv; + clock_timespec_t ts; - gettimeofday(&tv, NULL); + get_time(&ts); - return tv.tv_sec; + return ts.tv_sec; } /*---------------------------------------------------------------------------*/ void diff --git a/arch/platform/native/contiki-conf.h b/arch/platform/native/contiki-conf.h index f4f7bb1ba9e93c4822589e1d26caeb3fe1fbcf06..8d2c138204a327d5e7e6317be63f3be87a5fe422 100644 --- a/arch/platform/native/contiki-conf.h +++ b/arch/platform/native/contiki-conf.h @@ -37,7 +37,9 @@ #ifdef PROJECT_CONF_PATH #include PROJECT_CONF_PATH #endif /* PROJECT_CONF_PATH */ - +/*---------------------------------------------------------------------------*/ +#include "native-def.h" +/*---------------------------------------------------------------------------*/ #include <inttypes.h> #ifndef WIN32_LEAN_AND_MEAN #include <sys/select.h> @@ -58,18 +60,11 @@ int select_set_callback(int fd, const struct select_callback *callback); #define EEPROM_CONF_SIZE 1024 #endif -#define CCIF -#define CLIF - -/* These names are deprecated, use C99 names. */ -typedef uint8_t u8_t; -typedef uint16_t u16_t; -typedef uint32_t u32_t; -typedef int32_t s32_t; - -typedef unsigned short uip_stats_t; +typedef unsigned int uip_stats_t; +#ifndef UIP_CONF_BYTE_ORDER #define UIP_CONF_BYTE_ORDER UIP_LITTLE_ENDIAN +#endif #if NETSTACK_CONF_WITH_IPV6 @@ -96,10 +91,13 @@ typedef unsigned long clock_time_t; #define LOG_CONF_ENABLED 1 +#define PLATFORM_SUPPORTS_BUTTON_HAL 1 + /* Not part of C99 but actually present */ int strcasecmp(const char*, const char*); #define PLATFORM_CONF_PROVIDES_MAIN_LOOP 1 #define PLATFORM_CONF_MAIN_ACCEPTS_ARGS 1 +#define PLATFORM_CONF_SUPPORTS_STACK_CHECK 0 #endif /* CONTIKI_CONF_H_ */ diff --git a/arch/platform/native/dev/beep.c b/arch/platform/native/dev/beep.c deleted file mode 100644 index 64b8b439f6608b587f1965e43c313b55b2cb2b37..0000000000000000000000000000000000000000 --- a/arch/platform/native/dev/beep.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2004, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - * Author: Adam Dunkels <adam@sics.se> - * - */ -#include <stdio.h> -#include "dev/beep.h" - -void -beep_down(int n) -{ - printf("beep_down(%d)\n", n); -} - -void -beep_beep(int n) -{ - printf("beep_beep(%d)\n", n); -} - -void -beep_alarm(int alarmmode, int len) -{ - printf("beep_alarm(%d,%d)\n", alarmmode, len); -} - -void -beep_spinup(void) -{ - -} - -void beep(void) -{ - printf("%cbeep\n", 7); /*fflush(NULL);*/ -} - - -void -beep_off(void) -{ - -} -void -beep_on(void) -{ - -} - -void -beep_long(clock_time_t len) -{ -} - -void -beep_quick(int n) -{ - -} diff --git a/arch/platform/native/dev/beep.h b/arch/platform/native/dev/beep.h deleted file mode 100644 index f02db74812d18ce6af6f6e8964f270517e56a3e3..0000000000000000000000000000000000000000 --- a/arch/platform/native/dev/beep.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2005, Swedish Institute of Computer Science - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ - -/** - * \addtogroup native_platform - * @{ - */ - -/** - * \defgroup beeper Beeper interface - * @{ - */ - -/** - * \file - * Interface to the beeper. - * \author Adam Dunkels <adam@sics.se> - * - */ - -#ifndef BEEP_H_ -#define BEEP_H_ - -#define BEEP_ALARM1 1 -#define BEEP_ALARM2 2 - -#include "sys/clock.h" - -/** - * Beep for a specified time. - * - * This function causes the beeper to beep for the specified time. The - * time is measured in the same units as for the clock_delay() - * function. - * - * \note This function will hang the CPU during the beep. - * - * \note This function will stop any beep that was on previously when this - * function ends. - * - * \note If the beeper is turned off with beep_off() this call will still - * take the same time, though it will be silent. - * - * \param len The length of the beep. - * - */ -void beep_beep(int len); - -/** - * Beep an alarm for a specified time. - * - * This function causes the beeper to beep for the specified time. The - * time is measured in the same units as for the clock_delay() - * function. - * - * \note This function will hang the CPU during the beep. - * - * \note This function will stop any beep that was on previously when this - * function ends. - * - * \note If the beeper is turned off with beep_off() this call will still - * take the same time, though it will be silent. - * - * \param alarmmode The alarm mode (BEEP_ALARM1,BEEP_ALARM2) - * \param len The length of the beep. - * - */ -void beep_alarm(int alarmmode, int len); - -/** - * Produces a quick click-like beep. - * - * This function produces a short beep that sounds like a click. - * - */ -void beep(void); - -/** - * A beep with a pitch-bend down. - * - * This function produces a pitch-bend sound with deecreasing - * frequency. - * - * \param len The length of the pitch-bend. - * - */ -void beep_down(int len); - -/** - * Turn the beeper on. - * - * This function turns on the beeper. The beeper is turned off with - * the beep_off() function. - */ -void beep_on(void); - -/** - * Turn the beeper off. - * - * This function turns the beeper off after it has been turned on with - * beep_on(). - */ -void beep_off(void); - -/** - * Produce a sound similar to a hard-drive spinup. - * - * This function produces a sound that is intended to be similar to - * the sound a hard-drive makes when it starts. - * - */ -void beep_spinup(void); - -/** - * Beep for a long time (seconds) - * - * This function produces a beep with the specified length and will - * not return until the beep is complete. The length of the beep is - * specified using CLOCK_SECOND: a two second beep is CLOCK_SECOND * - * 2, and a quarter second beep is CLOCK_SECOND / 4. - * - * \note If the beeper is turned off with beep_off() this call will still - * take the same time, though it will be silent. - * - * \param len The length of the beep, measured in units of CLOCK_SECOND - */ -void beep_long(clock_time_t len); - -void beep_quick(int num); - -/** @} */ -/** @} */ - -#endif /* BEEP_H_ */ diff --git a/arch/platform/native/dev/button-sensor.c b/arch/platform/native/dev/button-sensor.c deleted file mode 100644 index 82dba1de9e2408f87ea0dea6a381dbaed18b60dd..0000000000000000000000000000000000000000 --- a/arch/platform/native/dev/button-sensor.c +++ /dev/null @@ -1,32 +0,0 @@ - -#include "dev/button-sensor.h" - -const struct sensors_sensor button_sensor; - -/*---------------------------------------------------------------------------*/ -void -button_press(void) -{ - sensors_changed(&button_sensor); -} -/*---------------------------------------------------------------------------*/ -static int -value(int type) -{ - return 0; -} -/*---------------------------------------------------------------------------*/ -static int -configure(int type, int value) -{ - return 0; -} -/*---------------------------------------------------------------------------*/ -static int -status(int type) -{ - return 0; -} -/*---------------------------------------------------------------------------*/ -SENSORS_SENSOR(button_sensor, BUTTON_SENSOR, - value, configure, status); diff --git a/arch/platform/native/dev/button-sensor.h b/arch/platform/native/dev/button-sensor.h deleted file mode 100644 index 2eadebd5f430818b0039404a50191171021661d2..0000000000000000000000000000000000000000 --- a/arch/platform/native/dev/button-sensor.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef BUTTON_SENSOR_H_ -#define BUTTON_SENSOR_H_ - -#include "lib/sensors.h" - -extern const struct sensors_sensor button_sensor; - -#define BUTTON_SENSOR "Button" - -void button_press(void); - -#endif /* BUTTON_SENSOR_H_ */ diff --git a/arch/platform/native/dev/buttons.c b/arch/platform/native/dev/buttons.c new file mode 100644 index 0000000000000000000000000000000000000000..359f7a4094d7f8ca5b95ceb089ec69923703cbf5 --- /dev/null +++ b/arch/platform/native/dev/buttons.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/button-hal.h" + +#include <stdint.h> +#include <string.h> +/*---------------------------------------------------------------------------*/ +button_hal_button_t *button_hal_buttons[] = { NULL }; +const uint8_t button_hal_button_count = 0; +/*---------------------------------------------------------------------------*/ diff --git a/arch/platform/native/dev/dummy-sensors.c b/arch/platform/native/dev/dummy-sensors.c deleted file mode 100644 index de84c7427f45c76e9c00cd9f88ae4d43a6374fe7..0000000000000000000000000000000000000000 --- a/arch/platform/native/dev/dummy-sensors.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2005, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Configurable Sensor Network Application - * Architecture for sensor nodes running the Contiki operating system. - * - * - * ----------------------------------------------------------------- - * - * Author : Adam Dunkels, Joakim Eriksson, Niclas Finne - * Created : 2005-11-01 - * Updated : $Date: 2010/01/14 20:15:55 $ - * $Revision: 1.2 $ - */ - -#include "dev/temperature-sensor.h" - -/*---------------------------------------------------------------------------*/ -static int -value(int type) -{ - return 0; -} -/*---------------------------------------------------------------------------*/ -static int -configure(int type, int c) -{ - return 0; -} -/*---------------------------------------------------------------------------*/ -static int -status(int type) -{ - return 0; -} -/*---------------------------------------------------------------------------*/ -SENSORS_SENSOR(temperature_sensor, TEMPERATURE_SENSOR, - value, configure, status); diff --git a/arch/platform/native/dev/irq.c b/arch/platform/native/dev/irq.c deleted file mode 100644 index 160e0c1b7a43bfd0a1d8720aa75716b4381fff24..0000000000000000000000000000000000000000 --- a/arch/platform/native/dev/irq.c +++ /dev/null @@ -1,5 +0,0 @@ -void -irq_init(void) -{ -} - diff --git a/arch/platform/native/dev/pir-sensor.c b/arch/platform/native/dev/pir-sensor.c deleted file mode 100644 index f13b7cc41ef022a9e7fd4e04857224890dccef1f..0000000000000000000000000000000000000000 --- a/arch/platform/native/dev/pir-sensor.c +++ /dev/null @@ -1,35 +0,0 @@ - -#include "dev/pir-sensor.h" - -const struct sensors_sensor pir_sensor; - -static int pir_value; - -/*---------------------------------------------------------------------------*/ -void -pir_sensor_changed(int strength) -{ - pir_value += strength; - sensors_changed(&pir_sensor); -} -/*---------------------------------------------------------------------------*/ -static int -value(int type) -{ - return pir_value; -} -/*---------------------------------------------------------------------------*/ -static int -configure(int type, int c) -{ - return 0; -} -/*---------------------------------------------------------------------------*/ -static int -status(int type) -{ - return 0; -} -/*---------------------------------------------------------------------------*/ -SENSORS_SENSOR(pir_sensor, PIR_SENSOR, - value, configure, status); diff --git a/arch/platform/native/dev/pir-sensor.h b/arch/platform/native/dev/pir-sensor.h deleted file mode 100644 index 3cbf181b6e47dcc5c7b15009cbce7d18b684ea45..0000000000000000000000000000000000000000 --- a/arch/platform/native/dev/pir-sensor.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef PIR_SENSOR_H_ -#define PIR_SENSOR_H_ - -#include "lib/sensors.h" - -extern const struct sensors_sensor pir_sensor; - -#define PIR_SENSOR "PIR" - -void pir_sensor_changed(int strength); - -#endif /* PIR_SENSOR_H_ */ diff --git a/arch/platform/native/dev/temperature-sensor.h b/arch/platform/native/dev/temperature-sensor.h deleted file mode 100644 index 89a13324c5a7324ab7b9c397de871d1168766bbd..0000000000000000000000000000000000000000 --- a/arch/platform/native/dev/temperature-sensor.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2005, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Configurable Sensor Network Application - * Architecture for sensor nodes running the Contiki operating system. - * - * - * ----------------------------------------------------------------- - * - * Author : Adam Dunkels, Joakim Eriksson, Niclas Finne - * Created : 2005-11-01 - * Updated : $Date: 2006/06/17 22:41:31 $ - * $Revision: 1.1 $ - */ - -#ifndef TEMPERATURE_SENSOR_H_ -#define TEMPERATURE_SENSOR_H_ - -#include "lib/sensors.h" - -extern const struct sensors_sensor temperature_sensor; - -#define TEMPERATURE_SENSOR "Temperature" - -#endif /* TEMPERATURE_SENSOR_H_ */ diff --git a/arch/platform/native/dev/vib-sensor.h b/arch/platform/native/dev/vib-sensor.h deleted file mode 100644 index c95caa9a5288e01e0a973f3a40f2f7502ef93b37..0000000000000000000000000000000000000000 --- a/arch/platform/native/dev/vib-sensor.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2005, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Configurable Sensor Network Application - * Architecture for sensor nodes running the Contiki operating system. - * - * - * ----------------------------------------------------------------- - * - * Author : Adam Dunkels, Joakim Eriksson, Niclas Finne - * Created : 2005-11-01 - * Updated : $Date: 2006/06/17 22:41:31 $ - * $Revision: 1.1 $ - */ - -#ifndef VIB_SENSOR_H_ -#define VIB_SENSOR_H_ - -#include "lib/sensors.h" - -extern const struct sensors_sensor vib_sensor; - -#define VIB_SENSOR "Vibration" - -void vib_sensor_changed(void); - -#endif /* VIB_SENSOR_H_ */ diff --git a/arch/platform/native/doxygen-group.txt b/arch/platform/native/doxygen-group.txt new file mode 100644 index 0000000000000000000000000000000000000000..705d2b8fa4e59ff53f9cca72354df83435c67b78 --- /dev/null +++ b/arch/platform/native/doxygen-group.txt @@ -0,0 +1,4 @@ +/** + * \defgroup native_platform Native platform + * \ingroup platform + */ diff --git a/arch/platform/native/platform.c b/arch/platform/native/platform.c index 577c688c065c29b82f249ac71656f9e477139286..c5c4f23e74d56542b4640a4a320ee0a8c6c9de6f 100644 --- a/arch/platform/native/platform.c +++ b/arch/platform/native/platform.c @@ -56,15 +56,14 @@ #include "net/netstack.h" #include "dev/serial-line.h" +#include "dev/button-hal.h" +#include "dev/gpio-hal.h" +#include "dev/leds.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-debug.h" #include "net/queuebuf.h" -#include "dev/button-sensor.h" -#include "dev/pir-sensor.h" -#include "dev/vib-sensor.h" - #if NETSTACK_CONF_WITH_IPV6 #include "net/ipv6/uip-ds6.h" #endif /* NETSTACK_CONF_WITH_IPV6 */ @@ -74,18 +73,53 @@ #define LOG_MODULE "Native" #define LOG_LEVEL LOG_LEVEL_MAIN +/*---------------------------------------------------------------------------*/ +/** + * \name Native Platform Configuration + * + * @{ + */ + +/* + * Defines the maximum number of file descriptors monitored by the platform + * main loop. + */ #ifdef SELECT_CONF_MAX #define SELECT_MAX SELECT_CONF_MAX #else #define SELECT_MAX 8 #endif +/* + * Defines the timeout (in msec) of the select operation if no monitored file + * descriptors becomes ready. + */ +#ifdef SELECT_CONF_TIMEOUT +#define SELECT_TIMEOUT SELECT_CONF_TIMEOUT +#else +#define SELECT_TIMEOUT 1000 +#endif + +/* + * Adds the STDIN file descriptor to the list of monitored file descriptors. + */ +#ifdef SELECT_CONF_STDIN +#define SELECT_STDIN SELECT_CONF_STDIN +#else +#define SELECT_STDIN 1 +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ + static const struct select_callback *select_callback[SELECT_MAX]; static int select_max = 0; -SENSORS(&pir_sensor, &vib_sensor, &button_sensor); +#ifdef PLATFORM_CONF_MAC_ADDR +static uint8_t mac_addr[] = PLATFORM_CONF_MAC_ADDR; +#else /* PLATFORM_CONF_MAC_ADDR */ +static uint8_t mac_addr[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; +#endif /* PLATFORM_CONF_MAC_ADDR */ -static uint8_t serial_id[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}; #if !NETSTACK_CONF_WITH_IPV6 static uint16_t node_id = 0x0102; #endif /* !NETSTACK_CONF_WITH_IPV6 */ @@ -122,6 +156,7 @@ select_set_callback(int fd, const struct select_callback *callback) return 0; } /*---------------------------------------------------------------------------*/ +#if SELECT_STDIN static int stdin_set_fd(fd_set *rset, fd_set *wset) { @@ -141,6 +176,7 @@ stdin_handle_fd(fd_set *rset, fd_set *wset) const static struct select_callback stdin_fd = { stdin_set_fd, stdin_handle_fd }; +#endif /* SELECT_STDIN */ /*---------------------------------------------------------------------------*/ static void set_lladdr(void) @@ -149,12 +185,12 @@ set_lladdr(void) memset(&addr, 0, sizeof(linkaddr_t)); #if NETSTACK_CONF_WITH_IPV6 - memcpy(addr.u8, serial_id, sizeof(addr.u8)); + memcpy(addr.u8, mac_addr, sizeof(addr.u8)); #else if(node_id == 0) { int i; for(i = 0; i < sizeof(linkaddr_t); ++i) { - addr.u8[i] = serial_id[7 - i]; + addr.u8[i] = mac_addr[7 - i]; } } else { addr.u8[0] = node_id & 0xff; @@ -164,6 +200,7 @@ set_lladdr(void) linkaddr_set_node_addr(&addr); } /*---------------------------------------------------------------------------*/ +#if NETSTACK_CONF_WITH_IPV6 static void set_global_address(void) { @@ -189,6 +226,7 @@ set_global_address(void) uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 1); uip_ds6_defrt_add(&ipaddr, 0); } +#endif /*---------------------------------------------------------------------------*/ int contiki_argc = 0; char **contiki_argv; @@ -216,6 +254,9 @@ platform_process_args(int argc, char**argv) void platform_init_stage_one() { + gpio_hal_init(); + button_hal_init(); + leds_init(); return; } /*---------------------------------------------------------------------------*/ @@ -223,6 +264,7 @@ void platform_init_stage_two() { set_lladdr(); + serial_line_init(); } /*---------------------------------------------------------------------------*/ void @@ -244,7 +286,9 @@ platform_init_stage_three() void platform_main_loop() { +#if SELECT_STDIN select_set_callback(STDIN_FILENO, &stdin_fd); +#endif /* SELECT_STDIN */ while(1) { fd_set fdr; fd_set fdw; @@ -256,7 +300,7 @@ platform_main_loop() retval = process_run(); tv.tv_sec = 0; - tv.tv_usec = retval ? 1 : 1000; + tv.tv_usec = retval ? 1 : SELECT_TIMEOUT; FD_ZERO(&fdr); FD_ZERO(&fdw); diff --git a/arch/platform/nrf52dk/Makefile.nrf52dk b/arch/platform/nrf52dk/Makefile.nrf52dk index 9c3778a73d74b5bf41fbbca8ca47e89eab0f2c99..7e931880a707a7fce050d0d77e2c42065021321b 100644 --- a/arch/platform/nrf52dk/Makefile.nrf52dk +++ b/arch/platform/nrf52dk/Makefile.nrf52dk @@ -13,19 +13,13 @@ ifeq ($(NRF52_USE_RTT),1) CONTIKI_TARGET_DIRS += rtt CONTIKI_SOURCEFILES += rtt-printf.c segger-rtt.c segger-rtt-printf.c else -CONTIKI_TARGET_DIRS += dbg-io CONTIKI_SOURCEFILES += dbg.c -CONTIKI_CPU_DIRS += ../arm/common/dbg-io -CONTIKI_CPU_SOURCEFILES += dbg-printf.c dbg-putchar.c dbg-snprintf.c dbg-sprintf.c strformat.c +MODULES += os/lib/dbg-io endif -CLEAN += *.nrf52dk - ### Unless the example dictates otherwise, build with code size optimisations switched off SMALL ?= 0 ### Define the CPU directory and pull in the correct CPU makefile. CONTIKI_CPU=$(CONTIKI)/arch/cpu/nrf52832 include $(CONTIKI_CPU)/Makefile.nrf52832 - -MODULES += os/net os/net/mac os/net/mac/framer diff --git a/arch/platform/nrf52dk/config/nrf_drv_config.h b/arch/platform/nrf52dk/config/nrf_drv_config.h index cfc3595b28320300e60f6e611d8f9f85e454430f..dd9e9b5de48fb6ce2fd63d4c23593db1e8dfb206 100644 --- a/arch/platform/nrf52dk/config/nrf_drv_config.h +++ b/arch/platform/nrf52dk/config/nrf_drv_config.h @@ -195,7 +195,7 @@ #if (UART0_ENABLED == 1) #define UART0_CONFIG_HWFC NRF_UART_HWFC_DISABLED #define UART0_CONFIG_PARITY NRF_UART_PARITY_EXCLUDED -#define UART0_CONFIG_BAUDRATE NRF_UART_BAUDRATE_38400 +#define UART0_CONFIG_BAUDRATE NRF_UART_BAUDRATE_115200 #define UART0_CONFIG_PSEL_TXD 6 #define UART0_CONFIG_PSEL_RXD 8 #define UART0_CONFIG_PSEL_CTS 7 diff --git a/arch/platform/nrf52dk/contiki-conf.h b/arch/platform/nrf52dk/contiki-conf.h index 2ab0898568a526c01a77c6683ae08bd82270d1f4..7b3b66314fa0830f4e1e8c7d45fdf03233bec065 100644 --- a/arch/platform/nrf52dk/contiki-conf.h +++ b/arch/platform/nrf52dk/contiki-conf.h @@ -41,6 +41,7 @@ #define CONTIKI_CONF_H #include <stdint.h> +#include <inttypes.h> /*---------------------------------------------------------------------------*/ /* Include Project Specific conf */ #ifdef PROJECT_CONF_PATH @@ -48,7 +49,8 @@ #endif /* PROJECT_CONF_PATH */ /*---------------------------------------------------------------------------*/ /* Include platform peripherals configuration */ -#include "platform-conf.h" +#include "nrf52dk-def.h" +#include "nrf52832-def.h" /*---------------------------------------------------------------------------*/ /** * \name Network Stack Configuration diff --git a/arch/platform/nrf52dk/dbg-io/dbg.h b/arch/platform/nrf52dk/dbg-io/dbg.h deleted file mode 100644 index 5d9568270b72f95ae0b35892ebff03428ae52f5c..0000000000000000000000000000000000000000 --- a/arch/platform/nrf52dk/dbg-io/dbg.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2015, Nordic Semiconductor - * All rights reserved. - * -3 * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ -/** - * \addtogroup nrf52dk - * @{ - * - * \addtogroup nrf52dk-dbg-io Debug IO over UART - * @{ - * - * \file - * Header file for the debug module. - * \author - * Wojciech Bober <wojciech.bober@nordicsemi.no> - * - */ -#ifndef DBG_H_ -#define DBG_H_ -/*---------------------------------------------------------------------------*/ -#include "contiki.h" -/*---------------------------------------------------------------------------*/ -/** - * \brief Print a stream of bytes - * \param seq A pointer to the stream - * \param len The number of bytes to print - * \return The number of printed bytes - */ -unsigned int dbg_send_bytes(const unsigned char *seq, unsigned int len); -/** - * \brief Print a character to debug output - * \param c Character to print - * \return Printed character - */ -int dbg_putchar(int c); -/*---------------------------------------------------------------------------*/ -#endif /* DBG_H_ */ -/*---------------------------------------------------------------------------*/ -/** - * @} - * @} - */ diff --git a/arch/platform/nrf52dk/dev/leds-arch.c b/arch/platform/nrf52dk/dev/leds-arch.c index 019589493390e374ff7a64d16458211cf12403ad..cda1317ef6419b9c639a93b77ab4876d570acc50 100644 --- a/arch/platform/nrf52dk/dev/leds-arch.c +++ b/arch/platform/nrf52dk/dev/leds-arch.c @@ -55,14 +55,14 @@ leds_arch_init(void) LEDS_OFF(LEDS_MASK); } /*---------------------------------------------------------------------------*/ -unsigned char +leds_mask_t leds_arch_get(void) { - return (unsigned char)(LED_IS_ON(LEDS_MASK) >> LED_START); + return (leds_mask_t)(LED_IS_ON(LEDS_MASK) >> LED_START); } /*---------------------------------------------------------------------------*/ void -leds_arch_set(unsigned char leds) +leds_arch_set(leds_mask_t leds) { unsigned int mask = (unsigned int)leds << LED_START; LEDS_OFF(LEDS_MASK); diff --git a/arch/platform/nrf52dk/doxygen-group.txt b/arch/platform/nrf52dk/doxygen-group.txt new file mode 100644 index 0000000000000000000000000000000000000000..e1f2c25e83dc0cfe4009208b8acd210de792f3e2 --- /dev/null +++ b/arch/platform/nrf52dk/doxygen-group.txt @@ -0,0 +1,4 @@ +/** + * \defgroup nrf52dk nRF52 Development Kit + * \ingroup platform + */ diff --git a/arch/platform/nrf52dk/platform-conf.h b/arch/platform/nrf52dk/nrf52dk-def.h similarity index 78% rename from arch/platform/nrf52dk/platform-conf.h rename to arch/platform/nrf52dk/nrf52dk-def.h index d40fd2b3e99c8696e3aa1da012846738df015334..0e387f0f0a20c610cd649faea0ba220bdbfef9b9 100644 --- a/arch/platform/nrf52dk/platform-conf.h +++ b/arch/platform/nrf52dk/nrf52dk-def.h @@ -43,8 +43,8 @@ * Wojciech Bober <wojciech.bober@nordicsemi.no> * */ -#ifndef PLATFORM_CONF_H_ -#define PLATFORM_CONF_H_ +#ifndef NRF52DK_DEF_H_ +#define NRF52DK_DEF_H_ #include "boards.h" @@ -60,16 +60,17 @@ * @{ */ #define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_LEGACY_API 1 #define LEDS_1 (1 << (LED_1 - LED_START)) // 1 #define LEDS_2 (1 << (LED_2 - LED_START)) // 2 #define LEDS_3 (1 << (LED_3 - LED_START)) // 4 #define LEDS_4 (1 << (LED_4 - LED_START)) // 8 -#define LEDS_GREEN LEDS_1 -#define LEDS_YELLOW LEDS_2 -#define LEDS_RED LEDS_3 -#define LEDS_BLUE LEDS_4 +#define LEDS_CONF_GREEN LEDS_1 +#define LEDS_CONF_YELLOW LEDS_2 +#define LEDS_CONF_RED LEDS_3 +#define LEDS_CONF_BLUE LEDS_4 #define LEDS_CONF_ALL (LEDS_1 | LEDS_2 | LEDS_3 | LEDS_4) @@ -107,39 +108,10 @@ */ #define PLATFORM_TIMER_INSTANCE_ID 1 -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name Compiler configuration and platform-specific type definitions - * - * Those values are not meant to be modified by the user - * @{ - */ -#define CLOCK_CONF_SECOND 128 - -/* Compiler configurations */ -#define CCIF -#define CLIF - -/* Platform typedefs */ -typedef uint32_t clock_time_t; -typedef uint32_t uip_stats_t; - -/* Clock (time) comparison macro */ -#define CLOCK_LT(a, b) ((signed long)((a) - (b)) < 0) - -#define RTIMER_ARCH_SECOND 62500 -/* - * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define - * RTIMER_CLOCK_DIFF to override this - */ -typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_DIFF(a,b) ((int32_t)((a)-(b))) - /** @} */ /*---------------------------------------------------------------------------*/ /** @} * @} * @} */ -#endif /* PLATFORM_CONF_H_ */ +#endif /* NRF52DK_DEF_H_ */ diff --git a/arch/platform/nrf52dk/platform.c b/arch/platform/nrf52dk/platform.c index a2ba55385a3f9799dfc90bc509a2f6579bd5b141..e48a3c05d23525d5913e623c3f5a3fa4475e6176 100644 --- a/arch/platform/nrf52dk/platform.c +++ b/arch/platform/nrf52dk/platform.c @@ -127,7 +127,7 @@ platform_init_stage_two(void) #ifdef UART0_ENABLED uart0_init(); #if SLIP_ARCH_CONF_ENABLE - slip_arch_init(); + #error Platform does not support SLIP #else uart0_set_input(serial_line_input_byte); serial_line_init(); diff --git a/arch/platform/openmote-cc2538/Makefile.openmote-cc2538 b/arch/platform/openmote-cc2538/Makefile.openmote-cc2538 index 94174a0a1d62dcc2dd66f4808caaff3fee6c849d..d3863fdbc379347a2ee9a3f48df3a1185b2558dd 100644 --- a/arch/platform/openmote-cc2538/Makefile.openmote-cc2538 +++ b/arch/platform/openmote-cc2538/Makefile.openmote-cc2538 @@ -15,19 +15,16 @@ PLATFORM_ROOT_DIR = $(CONTIKI)/arch/platform/$(TARGET) ### Include CONTIKI_TARGET_SOURCEFILES += platform.c board.c -CONTIKI_TARGET_SOURCEFILES += leds-arch.c button-sensor.c openmote-sensors.c +CONTIKI_TARGET_SOURCEFILES += leds-arch.c board-buttons.c openmote-sensors.c CONTIKI_TARGET_SOURCEFILES += antenna.c adxl346.c max44009.c sht21.c tps62730.c CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) -CLEAN += *.openmote-cc2538 - ### Define the CPU directory CONTIKI_CPU=$(CONTIKI)/arch/cpu/cc2538 include $(CONTIKI_CPU)/Makefile.cc2538 -MODULES += os/net os/net/mac os/net/mac/framer \ - os/storage/cfs +MODULES += os/storage/cfs PYTHON = python BSL_FLAGS += -e --bootloader-invert-lines -w -v -b 450000 diff --git a/arch/platform/openmote-cc2538/board.h b/arch/platform/openmote-cc2538/board.h index e3ce027f21fd2154083bbbb9d162d37882ebebe2..abb89b8e21b5ca11ac84dfa7a9cdadaeb35e44d6 100644 --- a/arch/platform/openmote-cc2538/board.h +++ b/arch/platform/openmote-cc2538/board.h @@ -63,21 +63,21 @@ * @{ */ /*---------------------------------------------------------------------------*/ -/* Some files include leds.h before us, so we need to get rid of defaults in - * leds.h before we provide correct definitions */ -#undef LEDS_GREEN -#undef LEDS_YELLOW -#undef LEDS_RED -#undef LEDS_CONF_ALL +#define LEDS_ARCH_L1_PORT GPIO_C_NUM +#define LEDS_ARCH_L1_PIN 4 +#define LEDS_ARCH_L2_PORT GPIO_C_NUM +#define LEDS_ARCH_L2_PIN 6 +#define LEDS_ARCH_L3_PORT GPIO_C_NUM +#define LEDS_ARCH_L3_PIN 7 +#define LEDS_ARCH_L4_PORT GPIO_C_NUM +#define LEDS_ARCH_L4_PIN 5 -#define LEDS_RED 16 /**< LED1 (Red) -> PC4 */ -#define LEDS_YELLOW 64 /**< LED2 (Yellow) -> PC6 */ -#define LEDS_GREEN 128 /**< LED3 (Green) -> PC7 */ -#define LEDS_ORANGE 32 /**< LED4 (Orange) -> PC5 */ -#define LEDS_CONF_ALL 240 +#define LEDS_CONF_RED 1 +#define LEDS_CONF_YELLOW 2 +#define LEDS_CONF_GREEN 4 +#define LEDS_CONF_ORANGE 8 -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 4 /** @} */ /*---------------------------------------------------------------------------*/ /** \name USB configuration @@ -128,6 +128,7 @@ #define BUTTON_USER_VECTOR GPIO_C_IRQn /* Notify various examples that we have Buttons */ #define PLATFORM_HAS_BUTTON 1 +#define PLATFORM_SUPPORTS_BUTTON_HAL 1 /** @} */ /*---------------------------------------------------------------------------*/ /** diff --git a/arch/platform/openmote-cc2538/contiki-conf.h b/arch/platform/openmote-cc2538/contiki-conf.h index 8458afbc9d81b5babbac6de9c8777496bf27fe10..daa20306581bb32ae83562b57140548859ac4945 100644 --- a/arch/platform/openmote-cc2538/contiki-conf.h +++ b/arch/platform/openmote-cc2538/contiki-conf.h @@ -40,6 +40,7 @@ * is comercialized by OpenMote Technologies since 2014. It is the first * commercial platform based on the powerful TI CC2538 SoC. It uses a * XBee form-factor to ease prototyping. + * @{ * * \file * Configuration for the OpenMote-CC2538 platform @@ -49,57 +50,14 @@ #include <stdint.h> #include <string.h> +#include <inttypes.h> /*---------------------------------------------------------------------------*/ /* Include Project Specific conf */ #ifdef PROJECT_CONF_PATH #include PROJECT_CONF_PATH #endif /* PROJECT_CONF_PATH */ /*---------------------------------------------------------------------------*/ -/** - * \name Compiler configuration and platform-specific type definitions - * - * Those values are not meant to be modified by the user - * @{ - */ -#define CLOCK_CONF_SECOND 128 - -/* Compiler configurations */ -#define CCIF -#define CLIF - -/* Platform typedefs */ -typedef uint32_t clock_time_t; -typedef uint32_t uip_stats_t; - -/* - * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define - * RTIMER_CLOCK_DIFF to override this - */ -typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_DIFF(a, b) ((int32_t)((a) - (b))) -/** @} */ -/*---------------------------------------------------------------------------*/ -/* 352us from calling transmit() until the SFD byte has been sent */ -#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(352)) -/* 192us as in datasheet but ACKs are not always received, so adjusted to 250us */ -#define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(250)) -#define RADIO_DELAY_BEFORE_DETECT 0 -#ifndef TSCH_CONF_BASE_DRIFT_PPM -/* The drift compared to "true" 10ms slots. - * Enable adaptive sync to enable compensation for this. - * Slot length 10000 usec - * 328 ticks - * Tick duration 30.517578125 usec - * Real slot duration 10009.765625 usec - * Target - real duration = -9.765625 usec - * TSCH_CONF_BASE_DRIFT_PPM -977 - */ -#define TSCH_CONF_BASE_DRIFT_PPM -977 -#endif - -#if MAC_CONF_WITH_TSCH -#define TSCH_CONF_HW_FRAME_FILTERING 0 -#endif /* MAC_CONF_WITH_TSCH */ +#include "cc2538-def.h" /*---------------------------------------------------------------------------*/ /** * \name Serial Boot Loader Backdoor configuration @@ -129,290 +87,11 @@ typedef uint32_t rtimer_clock_t; #endif /** @} */ /*---------------------------------------------------------------------------*/ -/** - * \name CFS configuration - * - * @{ - */ -#ifndef COFFEE_CONF_SIZE -#define COFFEE_CONF_SIZE (4 * COFFEE_SECTOR_SIZE) -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name Watchdog Timer configuration - * - * @{ - */ -#ifndef WATCHDOG_CONF_ENABLE -#define WATCHDOG_CONF_ENABLE 1 /**< Enable the watchdog timer */ -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name USB 'core' configuration - * - * Those values are not meant to be modified by the user, except where stated - * otherwise - * @{ - */ -#define CTRL_EP_SIZE 8 -#define USB_EP1_SIZE 32 -#define USB_EP2_SIZE 64 -#define USB_EP3_SIZE 64 -#define USB_ARCH_WRITE_NOTIFY 0 - -#ifndef USB_ARCH_CONF_DMA -#define USB_ARCH_CONF_DMA 1 /**< Change to Enable/Disable USB DMA */ - -#endif -/** @} */ - -/*---------------------------------------------------------------------------*/ -/** - * \name uDMA Configuration and channel allocations - * - * @{ - */ -#define USB_ARCH_CONF_RX_DMA_CHAN 0 /**< USB -> RAM DMA channel */ -#define USB_ARCH_CONF_TX_DMA_CHAN 1 /**< RAM -> USB DMA channel */ -#define CC2538_RF_CONF_TX_DMA_CHAN 2 /**< RF -> RAM DMA channel */ -#define CC2538_RF_CONF_RX_DMA_CHAN 3 /**< RAM -> RF DMA channel */ -#define UDMA_CONF_MAX_CHANNEL CC2538_RF_CONF_RX_DMA_CHAN -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name Character I/O Configuration - * - * @{ - */ -#ifndef UART_CONF_ENABLE -#define UART_CONF_ENABLE 1 /**< Enable/Disable UART I/O */ -#endif - -#ifndef UART0_CONF_BAUD_RATE -#define UART0_CONF_BAUD_RATE 115200 /**< Default UART0 baud rate */ -#endif - -#ifndef UART1_CONF_BAUD_RATE -#define UART1_CONF_BAUD_RATE 115200 /**< Default UART1 baud rate */ -#endif - -#ifndef SLIP_ARCH_CONF_USB -#define SLIP_ARCH_CONF_USB 0 /**< SLIP over UART by default */ -#endif - -#ifndef DBG_CONF_USB -#define DBG_CONF_USB 0 /**< All debugging over UART by default */ -#endif - -#ifndef SERIAL_LINE_CONF_UART -#define SERIAL_LINE_CONF_UART 0 /**< UART to use with serial line */ -#endif - -#if !SLIP_ARCH_CONF_USB -#ifndef SLIP_ARCH_CONF_UART -#define SLIP_ARCH_CONF_UART 0 /**< UART to use with SLIP */ -#endif -#endif - -#if !DBG_CONF_USB -#ifndef DBG_CONF_UART -#define DBG_CONF_UART 0 /**< UART to use for debugging */ -#endif -#endif - -#ifndef UART1_CONF_UART -#define UART1_CONF_UART 0 /**< UART to use for examples relying on - the uart1_* API */ -#endif - -#ifndef SLIP_ARCH_CONF_ENABLED -/* - * Determine whether we need SLIP - * This will keep working while UIP_FALLBACK_INTERFACE and CMD_CONF_OUTPUT - * keep using SLIP - */ -#if defined(UIP_FALLBACK_INTERFACE) || defined(CMD_CONF_OUTPUT) -#define SLIP_ARCH_CONF_ENABLED 1 -#endif -#endif - -/** - * \brief Define this as 1 to build a headless node. - * - * The UART will not be initialised its clock will be gated, offering some - * energy savings. The USB will not be initialised either - */ -#ifndef CC2538_CONF_QUIET -#define CC2538_CONF_QUIET 0 -#endif - -/* CC2538_CONF_QUIET is hard and overrides all other related defines */ -#if CC2538_CONF_QUIET -#undef USB_SERIAL_CONF_ENABLE -#define USB_SERIAL_CONF_ENABLE 0 - -#undef UART_CONF_ENABLE -#define UART_CONF_ENABLE 0 -#endif /* CC2538_CONF_QUIET */ - -/** - * \brief Enable the USB core only if we need it - */ -#ifndef USB_SERIAL_CONF_ENABLE -#define USB_SERIAL_CONF_ENABLE \ - ((SLIP_ARCH_CONF_USB && SLIP_ARCH_CONF_ENABLED) || \ - (MAC_CONF_WITH_TSCH && (SLIP_ARCH_CONF_ENABLED || BUILD_WITH_SHELL)) || \ - DBG_CONF_USB) -#endif - -/* - * If debugging and SLIP use the same peripheral, this will be 1. Don't modify - * this - */ -#if SLIP_ARCH_CONF_ENABLED -#define DBG_CONF_SLIP_MUX (SLIP_ARCH_CONF_USB == DBG_CONF_USB && \ - (SLIP_ARCH_CONF_USB || \ - SLIP_ARCH_CONF_UART == DBG_CONF_UART)) -#endif - -/* - * Automatic detection of whether a specific UART is in use - */ -#define UART_IN_USE_BY_SERIAL_LINE(u) (SERIAL_LINE_CONF_UART == (u)) -#define UART_IN_USE_BY_SLIP(u) (SLIP_ARCH_CONF_ENABLED && \ - !SLIP_ARCH_CONF_USB && \ - SLIP_ARCH_CONF_UART == (u)) -#define UART_IN_USE_BY_DBG(u) (!DBG_CONF_USB && DBG_CONF_UART == (u)) -#define UART_IN_USE_BY_UART1(u) (UART1_CONF_UART == (u)) - -#define UART_IN_USE(u) ( \ - UART_CONF_ENABLE && \ - (UART_IN_USE_BY_SERIAL_LINE(u) || \ - UART_IN_USE_BY_SLIP(u) || \ - UART_IN_USE_BY_DBG(u) || \ - UART_IN_USE_BY_UART1(u)) \ - ) -/** @} */ -/*---------------------------------------------------------------------------*/ /* board.h assumes that basic configuration is done */ #include "board.h" /*---------------------------------------------------------------------------*/ -/** - * \name Radio Configuration - * - * @{ - */ - -#ifndef NETSTACK_CONF_RADIO -#define NETSTACK_CONF_RADIO cc2538_rf_driver -#endif - -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name LPM configuration - * @{ - */ -#ifndef LPM_CONF_ENABLE -#define LPM_CONF_ENABLE 1 /**< Set to 0 to disable LPM entirely */ -#endif - -/** - * \brief Maximum PM - * - * The SoC will never drop to a Power Mode deeper than the one specified here. - * 0 for PM0, 1 for PM1 and 2 for PM2 - */ -#ifndef LPM_CONF_MAX_PM -#define LPM_CONF_MAX_PM 1 -#endif - -#ifndef LPM_CONF_STATS -#define LPM_CONF_STATS 0 /**< Set to 1 to enable LPM-related stats */ -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name IEEE address configuration - * - * Used to generate our link-layer & IPv6 address - * @{ - */ -/** - * \brief Location of the IEEE address - * 0 => Read from InfoPage, - * 1 => Use a hardcoded address, configured by IEEE_ADDR_CONF_ADDRESS - */ -#ifndef IEEE_ADDR_CONF_HARDCODED -#define IEEE_ADDR_CONF_HARDCODED 0 -#endif - -/** - * \brief The hardcoded IEEE address to be used when IEEE_ADDR_CONF_HARDCODED - * is defined as 1 - */ -#ifndef IEEE_ADDR_CONF_ADDRESS -#define IEEE_ADDR_CONF_ADDRESS { 0x00, 0x12, 0x4B, 0x00, 0x89, 0xAB, 0xCD, 0xEF } -#endif - -/** - * \brief Location of the IEEE address in the InfoPage when - * IEEE_ADDR_CONF_HARDCODED is defined as 0 - * 0 => Use the primary address location - * 1 => Use the secondary address location - */ -#ifndef IEEE_ADDR_CONF_USE_SECONDARY_LOCATION -#define IEEE_ADDR_CONF_USE_SECONDARY_LOCATION 0 -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name RF configuration - * - * @{ - */ -/* RF Config */ - -#ifdef RF_CHANNEL -#define CC2538_RF_CONF_CHANNEL RF_CHANNEL -#endif - -#ifndef CC2538_RF_CONF_CHANNEL -#define CC2538_RF_CONF_CHANNEL 26 -#endif /* CC2538_RF_CONF_CHANNEL */ - -#ifndef CC2538_RF_CONF_AUTOACK -#define CC2538_RF_CONF_AUTOACK 1 /**< RF H/W generates ACKs */ -#endif /* CC2538_CONF_AUTOACK */ - -#ifndef CC2538_RF_CONF_TX_USE_DMA -#define CC2538_RF_CONF_TX_USE_DMA 1 /**< RF TX over DMA */ -#endif - -#ifndef CC2538_RF_CONF_RX_USE_DMA -#define CC2538_RF_CONF_RX_USE_DMA 1 /**< RF RX over DMA */ -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name Security - * - * @{ - */ -#ifndef CRYPTO_CONF_INIT -#define CRYPTO_CONF_INIT 1 /**< Whether to init cryptoprocessor */ -#endif - -#ifndef AES_128_CONF -#define AES_128_CONF cc2538_aes_128_driver /**< AES-128 driver */ -#endif - -#ifndef CCM_STAR_CONF -#define CCM_STAR_CONF cc2538_ccm_star_driver /**< AES-CCM* driver */ -#endif - +/* Include CPU-related configuration */ +#include "cc2538-conf.h" /*---------------------------------------------------------------------------*/ #endif /* CONTIKI_CONF_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/arch/platform/openmote-cc2538/dev/board-buttons.c b/arch/platform/openmote-cc2538/dev/board-buttons.c new file mode 100644 index 0000000000000000000000000000000000000000..654302f24e8ecaed89b2571f94a49fe3acb4e144 --- /dev/null +++ b/arch/platform/openmote-cc2538/dev/board-buttons.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-cc2538 + * @{ + * + * \defgroup openmote-cc2538-buttons OpenMote-CC2538 user button + * + * Generic module controlling the user button on the OpenMote-CC2538 + * @{ + * + * \file + * Defines the OpenMote-CC2538 user button for use with the button HAL + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/button-hal.h" +/*---------------------------------------------------------------------------*/ +BUTTON_HAL_BUTTON(button_user, "User button", \ + GPIO_PORT_PIN_TO_GPIO_HAL_PIN(BUTTON_USER_PORT, BUTTON_USER_PIN), \ + GPIO_HAL_PIN_CFG_PULL_UP, BUTTON_HAL_ID_USER_BUTTON, true); +/*---------------------------------------------------------------------------*/ +BUTTON_HAL_BUTTONS(&button_user); +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/arch/platform/openmote-cc2538/dev/button-sensor.c b/arch/platform/openmote-cc2538/dev/button-sensor.c deleted file mode 100644 index 9c6a7d6c88fad01bb1a5e9642b5c2e5b0c7589cc..0000000000000000000000000000000000000000 --- a/arch/platform/openmote-cc2538/dev/button-sensor.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ -/*---------------------------------------------------------------------------*/ -/** - * \addtogroup openmote-button-sensor - * @{ - * - * \file - * Driver for for the OpenMote-CC2538 user button - */ -/*---------------------------------------------------------------------------*/ -#include "contiki.h" -#include "dev/nvic.h" -#include "dev/ioc.h" -#include "dev/gpio.h" -#include "dev/button-sensor.h" -#include "sys/timer.h" -#include "sys/ctimer.h" -#include "sys/process.h" - -#include <stdint.h> -#include <string.h> -/*---------------------------------------------------------------------------*/ -#define BUTTON_USER_PORT_BASE GPIO_PORT_TO_BASE(BUTTON_USER_PORT) -#define BUTTON_USER_PIN_MASK GPIO_PIN_MASK(BUTTON_USER_PIN) -/*---------------------------------------------------------------------------*/ -#define DEBOUNCE_DURATION (CLOCK_SECOND >> 4) - -static struct timer debouncetimer; -/*---------------------------------------------------------------------------*/ -static clock_time_t press_duration = 0; -static struct ctimer press_counter; -static uint8_t press_event_counter; - -process_event_t button_press_duration_exceeded; -/*---------------------------------------------------------------------------*/ -static void -duration_exceeded_callback(void *data) -{ - press_event_counter++; - process_post(PROCESS_BROADCAST, button_press_duration_exceeded, - &press_event_counter); - ctimer_set(&press_counter, press_duration, duration_exceeded_callback, - NULL); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Retrieves the value of the button pin - * \param type Returns the pin level or the counter of press duration events. - * type == BUTTON_SENSOR_VALUE_TYPE_LEVEL or - * type == BUTTON_SENSOR_VALUE_TYPE_PRESS_DURATION - * respectively - */ -static int -value(int type) -{ - switch(type) { - case BUTTON_SENSOR_VALUE_TYPE_LEVEL: - return GPIO_READ_PIN(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); - case BUTTON_SENSOR_VALUE_TYPE_PRESS_DURATION: - return press_event_counter; - } - - return 0; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Callback registered with the GPIO module. Gets fired with a button - * port/pin generates an interrupt - * \param port The port number that generated the interrupt - * \param pin The pin number that generated the interrupt. This is the pin - * absolute number (i.e. 0, 1, ..., 7), not a mask - */ -static void -btn_callback(uint8_t port, uint8_t pin) -{ - if(!timer_expired(&debouncetimer)) { - return; - } - - timer_set(&debouncetimer, DEBOUNCE_DURATION); - - if(press_duration) { - press_event_counter = 0; - if(value(BUTTON_SENSOR_VALUE_TYPE_LEVEL) == BUTTON_SENSOR_PRESSED_LEVEL) { - ctimer_set(&press_counter, press_duration, duration_exceeded_callback, - NULL); - } else { - ctimer_stop(&press_counter); - } - } - - sensors_changed(&button_sensor); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Init function for the User button. - * \param type SENSORS_ACTIVE: Activate / Deactivate the sensor (value == 1 - * or 0 respectively) - * - * \param value Depends on the value of the type argument - * \return Depends on the value of the type argument - */ -static int -config_user(int type, int value) -{ - switch(type) { - case SENSORS_HW_INIT: - button_press_duration_exceeded = process_alloc_event(); - - /* Software controlled */ - GPIO_SOFTWARE_CONTROL(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); - - /* Set pin to input */ - GPIO_SET_INPUT(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); - - /* Enable edge detection */ - GPIO_DETECT_EDGE(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); - - /* Both Edges */ - GPIO_TRIGGER_BOTH_EDGES(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); - - ioc_set_over(BUTTON_USER_PORT, BUTTON_USER_PIN, IOC_OVERRIDE_PUE); - - gpio_register_callback(btn_callback, BUTTON_USER_PORT, BUTTON_USER_PIN); - break; - case SENSORS_ACTIVE: - if(value) { - GPIO_ENABLE_INTERRUPT(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); - NVIC_EnableIRQ(BUTTON_USER_VECTOR); - } else { - GPIO_DISABLE_INTERRUPT(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); - NVIC_DisableIRQ(BUTTON_USER_VECTOR); - } - return value; - case BUTTON_SENSOR_CONFIG_TYPE_INTERVAL: - press_duration = (clock_time_t)value; - break; - default: - break; - } - - return 1; -} -/*---------------------------------------------------------------------------*/ -SENSORS_SENSOR(button_sensor, BUTTON_SENSOR, value, config_user, NULL); -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/openmote-cc2538/dev/leds-arch.c b/arch/platform/openmote-cc2538/dev/leds-arch.c index 28454dacf56b22a96dec5c656bdc869271404ee3..3c1fe333f813eada63d7b5614f166345fb6f1f8c 100644 --- a/arch/platform/openmote-cc2538/dev/leds-arch.c +++ b/arch/platform/openmote-cc2538/dev/leds-arch.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright @@ -26,48 +27,30 @@ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ -/*---------------------------------------------------------------------------*/ -/** - * \addtogroup openmote-cc2538 - * @{ - * - * \defgroup openmote-leds OpenMote-CC2538 LED driver - * @{ - * - * \file - * LED driver implementation for the OpenMote-CC2538 platform */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "reg.h" #include "dev/leds.h" -#include "dev/gpio.h" -/*---------------------------------------------------------------------------*/ -#define LEDS_GPIO_PIN_MASK LEDS_ALL -/*---------------------------------------------------------------------------*/ -void -leds_arch_init(void) -{ - GPIO_SET_OUTPUT(GPIO_C_BASE, LEDS_GPIO_PIN_MASK); -} +#include "dev/gpio-hal.h" + +#include <stdbool.h> /*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - return GPIO_READ_PIN(GPIO_C_BASE, LEDS_GPIO_PIN_MASK); -} +const leds_t leds_arch_leds[] = { + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L1_PORT, LEDS_ARCH_L1_PIN), + .negative_logic = false + }, + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L2_PORT, LEDS_ARCH_L2_PIN), + .negative_logic = false + }, + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L3_PORT, LEDS_ARCH_L3_PIN), + .negative_logic = false + }, + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L4_PORT, LEDS_ARCH_L4_PIN), + .negative_logic = false + }, +}; /*---------------------------------------------------------------------------*/ -void -leds_arch_set(unsigned char leds) -{ - GPIO_WRITE_PIN(GPIO_C_BASE, LEDS_GPIO_PIN_MASK, leds); -} -/*---------------------------------------------------------------------------*/ -/** - * @} - * @} - */ diff --git a/arch/platform/openmote-cc2538/dev/openmote-sensors.c b/arch/platform/openmote-cc2538/dev/openmote-sensors.c index 3b55e4cbb1594ff958cff66df330df482c1e8b3d..772087fa9902a662c910575e00864e05b1bc769e 100644 --- a/arch/platform/openmote-cc2538/dev/openmote-sensors.c +++ b/arch/platform/openmote-cc2538/dev/openmote-sensors.c @@ -52,7 +52,7 @@ /** * \brief Exports a global symbol to be used by the sensor API */ -SENSORS(&button_sensor, &cc2538_temp_sensor); +SENSORS(&cc2538_temp_sensor); /*---------------------------------------------------------------------------*/ /** * @} diff --git a/arch/platform/openmote-cc2538/dev/openmote-sensors.h b/arch/platform/openmote-cc2538/dev/openmote-sensors.h index a765dbd3d7e3f45229447fda126ee6427f164e0c..811518625b2859e2695037da806255aed6c68166 100644 --- a/arch/platform/openmote-cc2538/dev/openmote-sensors.h +++ b/arch/platform/openmote-cc2538/dev/openmote-sensors.h @@ -49,7 +49,6 @@ /*---------------------------------------------------------------------------*/ #include "lib/sensors.h" #include "dev/cc2538-sensors.h" -#include "dev/button-sensor.h" /*---------------------------------------------------------------------------*/ #endif /* OPENMOTE_SENSORS_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/arch/platform/openmote-cc2538/platform.c b/arch/platform/openmote-cc2538/platform.c index 7cb583a166cfab2cd05cd6c72ed96ca6f1119284..c226785c6690501f5fc91fd7c6d853ef566a851b 100644 --- a/arch/platform/openmote-cc2538/platform.c +++ b/arch/platform/openmote-cc2538/platform.c @@ -32,7 +32,7 @@ */ /*---------------------------------------------------------------------------*/ /** - * \addtogroup platform + * \addtogroup cc2538-platforms * @{ * * \defgroup openmote-cc2538 OpenMote-CC2538 platform @@ -55,8 +55,10 @@ #include "dev/cc2538-rf.h" #include "dev/udma.h" #include "dev/crypto.h" +#include "dev/button-hal.h" #include "usb/usb-serial.h" #include "lib/random.h" +#include "lib/sensors.h" #include "net/netstack.h" #include "net/mac/framer/frame802154.h" #include "net/linkaddr.h" @@ -82,7 +84,7 @@ void board_init(void); /*---------------------------------------------------------------------------*/ static void -fade(unsigned char l) +fade(leds_mask_t l) { volatile int i; int k, j; @@ -91,11 +93,11 @@ fade(unsigned char l) leds_on(l); for(i = 0; i < j; ++i) { - asm("nop"); + __asm("nop"); } leds_off(l); for(i = 0; i < 400 - j; ++i) { - asm("nop"); + __asm("nop"); } } } @@ -111,9 +113,6 @@ set_rf_params(void) short_addr = ext_addr[7]; short_addr |= ext_addr[6] << 8; - /* Populate linkaddr_node_addr. Maintain endianness */ - memcpy(&linkaddr_node_addr, &ext_addr[8 - LINKADDR_SIZE], LINKADDR_SIZE); - NETSTACK_RADIO.set_value(RADIO_PARAM_PAN_ID, IEEE802154_PANID); NETSTACK_RADIO.set_value(RADIO_PARAM_16BIT_ADDR, short_addr); NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, CC2538_RF_CHANNEL); @@ -157,7 +156,10 @@ platform_init_stage_two() crypto_disable(); #endif - set_rf_params(); + /* Populate linkaddr_node_addr */ + ieee_addr_cpy_to(linkaddr_node_addr.u8, LINKADDR_SIZE); + + button_hal_init(); INTERRUPTS_ENABLE(); @@ -169,14 +171,14 @@ platform_init_stage_three() { LOG_INFO("%s\n", BOARD_STRING); + set_rf_params(); + board_init(); soc_print_info(); process_start(&sensors_process, NULL); - SENSORS_ACTIVATE(button_sensor); - fade(LEDS_GREEN); } /*---------------------------------------------------------------------------*/ diff --git a/arch/platform/sky/Makefile.common b/arch/platform/sky/Makefile.common index 1dea288463f2a9f922abccdafacdbf5fbf810f5a..081ffaa9fb0fdd5a470b90882f65f399a242953d 100644 --- a/arch/platform/sky/Makefile.common +++ b/arch/platform/sky/Makefile.common @@ -1,6 +1,6 @@ # $Id: Makefile.common,v 1.3 2010/08/24 16:24:11 joxe Exp $ -ARCH=spi.c ds2411.c xmem.c i2c.c node-id.c sensors.c cfs-coffee.c \ +ARCH=spi-legacy.c ds2411.c xmem.c i2c.c node-id.c sensors.c cfs-coffee.c \ cc2420.c cc2420-arch.c cc2420-arch-sfd.c \ sky-sensors.c uip-ipchksum.c \ uart1.c slip_uart1.c uart1-putchar.c platform.c diff --git a/arch/platform/sky/Makefile.sky b/arch/platform/sky/Makefile.sky index 9f86b64991f6620a2966d661857fa39dace92047..0398486b0a024c039c18651c590083b7e186b35b 100644 --- a/arch/platform/sky/Makefile.sky +++ b/arch/platform/sky/Makefile.sky @@ -6,6 +6,4 @@ CONTIKI_TARGET_SOURCEFILES += contiki-sky-platform.c \ include $(CONTIKI)/arch/platform/sky/Makefile.common -MODULES += os/net/mac os/net/mac/framer os/net \ - arch/dev/cc2420 arch/dev/sht11 arch/dev/ds2411 \ - os/storage/cfs +MODULES += arch/dev/cc2420 arch/dev/sht11 arch/dev/ds2411 os/storage/cfs diff --git a/arch/platform/sky/contiki-conf.h b/arch/platform/sky/contiki-conf.h index 52fc596a8d15b2fe47db02041037a80cc9ca5ca9..500e00e0809f6cc388ace8276d27983205cedb47 100644 --- a/arch/platform/sky/contiki-conf.h +++ b/arch/platform/sky/contiki-conf.h @@ -7,12 +7,14 @@ #ifdef PROJECT_CONF_PATH #include PROJECT_CONF_PATH #endif /* PROJECT_CONF_PATH */ - -#ifdef PLATFORM_CONF_H -#include PLATFORM_CONF_H -#else -#include "platform-conf.h" -#endif /* PLATFORM_CONF_H */ +/*---------------------------------------------------------------------------*/ +#include "sky-def.h" +#include "msp430-def.h" +/*---------------------------------------------------------------------------*/ +/* Map RF_CHANNEL to cc2420 default channel */ +#ifdef RF_CHANNEL +#define CC2420_CONF_CHANNEL RF_CHANNEL +#endif /* RF_CHANNEL */ /* Configure radio driver */ #ifndef NETSTACK_CONF_RADIO @@ -30,12 +32,16 @@ #define UIP_CONF_BUFFER_SIZE 240 #endif -/* Platform-specific checksum implementation */ -#define UIP_ARCH_IPCHKSUM 1 - /* Platform-specific (H/W) AES implementation */ #ifndef AES_128_CONF #define AES_128_CONF cc2420_aes_128_driver #endif /* AES_128_CONF */ +/* Disable the stack check library by default: .rom overflow otherwise */ +#ifndef STACK_CHECK_CONF_ENABLED +#define STACK_CHECK_CONF_ENABLED 0 +#endif +/*---------------------------------------------------------------------------*/ +#include "msp430-conf.h" +/*---------------------------------------------------------------------------*/ #endif /* CONTIKI_CONF_H */ diff --git a/arch/platform/sky/dev/i2c.c b/arch/platform/sky/dev/i2c.c index b9d10a9c72bf34d2adb6d3abaae34eb707ed66f9..1acbe897a21d9689292a1c7cf65ec310a26df5b1 100644 --- a/arch/platform/sky/dev/i2c.c +++ b/arch/platform/sky/dev/i2c.c @@ -41,7 +41,7 @@ #include <stdio.h> #include <contiki.h> -#include <dev/spi.h> +#include "dev/spi-legacy.h" #include <dev/leds.h> #include "dev/i2c.h" diff --git a/arch/platform/sky/dev/xmem.c b/arch/platform/sky/dev/xmem.c index 21814ad041854a316bf4327076845a5f6a0267a7..4ff525bb8ad15805b134ba03e1b3ed5210fabd1c 100644 --- a/arch/platform/sky/dev/xmem.c +++ b/arch/platform/sky/dev/xmem.c @@ -43,7 +43,7 @@ #include <stdio.h> #include <string.h> -#include "dev/spi.h" +#include "dev/spi-legacy.h" #include "dev/xmem.h" #include "dev/watchdog.h" diff --git a/arch/platform/sky/platform.c b/arch/platform/sky/platform.c index b14858d9a82ee5a724f99b0c12cebcb1902c7f4f..d7147134099f8715c639cd71f3dee8c47f2cf00f 100644 --- a/arch/platform/sky/platform.c +++ b/arch/platform/sky/platform.c @@ -51,7 +51,6 @@ #include "sys/node-id.h" #include "cfs-coffee-arch.h" #include "cfs/cfs-coffee.h" -#include "sys/autostart.h" #if DCOSYNCH_CONF_ENABLED static struct timer mgt_timer; @@ -200,18 +199,18 @@ platform_init_stage_three(void) cc2420_set_pan_addr(IEEE802154_PANID, shortaddr, longaddr); if(node_id > 0) { - LOG_INFO("Node id is set to %u.\n", node_id); + LOG_INFO("Node id: %u\n", node_id); } else { - LOG_INFO("Node id is not set.\n"); + LOG_INFO("Node id: N/A\n"); } #if NETSTACK_CONF_WITH_IPV6 - LOG_INFO("%s, radio channel %u, CCA threshold %i\n", + LOG_INFO("%s, rf channel %u, CCA threshold %i\n", NETSTACK_MAC.name, CC2420_CONF_CHANNEL, CC2420_CONF_CCA_THRESH); #else /* NETSTACK_CONF_WITH_IPV6 */ - LOG_INFO("%s, radio channel %u\n", + LOG_INFO("%s, rf channel %u\n", NETSTACK_MAC.name, CC2420_CONF_CHANNEL); #endif /* NETSTACK_CONF_WITH_IPV6 */ diff --git a/arch/platform/sky/platform-conf.h b/arch/platform/sky/sky-def.h similarity index 92% rename from arch/platform/sky/platform-conf.h rename to arch/platform/sky/sky-def.h index 7a8c584fe6fad7264c4a03dfbee262d1a92d3aab..edab43ee767f3328f082411e06bc89a55b92a9fe 100644 --- a/arch/platform/sky/platform-conf.h +++ b/arch/platform/sky/sky-def.h @@ -36,16 +36,13 @@ * Joakim Eriksson <joakime@sics.se> */ -#ifndef PLATFORM_CONF_H_ -#define PLATFORM_CONF_H_ +#ifndef SKY_DEF_H_ +#define SKY_DEF_H_ /* * Definitions below are dictated by the hardware and not really * changeable! */ -/* Platform TMOTE_SKY */ -#define TMOTE_SKY 1 - /* Delay between GO signal and SFD: radio fixed delay + 4Bytes preample + 1B SFD -- 1Byte time is 32us * ~327us + 129preample = 456 us */ #define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(456)) @@ -55,6 +52,9 @@ /* Delay between the SFD finishes arriving and it is detected in software */ #define RADIO_DELAY_BEFORE_DETECT 0 +/* Disable TSCH frame filtering */ +#define TSCH_CONF_HW_FRAME_FILTERING 0 + #define PLATFORM_HAS_LEDS 1 #define PLATFORM_HAS_BUTTON 1 #define PLATFORM_HAS_LIGHT 1 @@ -62,31 +62,9 @@ #define PLATFORM_HAS_SHT11 1 #define PLATFORM_HAS_RADIO 1 -/* Map RF_CHANNEL to cc2420 default channel */ -#ifdef RF_CHANNEL -#define CC2420_CONF_CHANNEL RF_CHANNEL -#endif /* RF_CHANNEL */ - /* CPU target speed in Hz */ #define F_CPU 3900000uL /*2457600uL*/ -/* Our clock resolution, this is the same as Unix HZ. */ -#define CLOCK_CONF_SECOND 128UL - -#define BAUD2UBR(baud) ((F_CPU/baud)) - -#define CCIF -#define CLIF - -#define HAVE_STDINT_H -#include "msp430def.h" - - -/* Types for clocks and uip_stats */ -typedef unsigned short uip_stats_t; -typedef unsigned long clock_time_t; -typedef long off_t; - /* the low-level radio driver */ #define NETSTACK_CONF_RADIO cc2420_driver @@ -97,6 +75,8 @@ typedef long off_t; #define LEDS_CONF_GREEN 0x20 #define LEDS_CONF_YELLOW 0x40 +#define LEDS_CONF_LEGACY_API 1 + /* DCO speed resynchronization for more robust UART, etc. */ #ifndef DCOSYNCH_CONF_ENABLED #define DCOSYNCH_CONF_ENABLED (!(MAC_CONF_WITH_TSCH)) /* TSCH needs timerB @@ -230,4 +210,7 @@ for SFD timestamping */ #define CC2420_SPI_DISABLE() (CC2420_CSN_PORT(OUT) |= BV(CC2420_CSN_PIN)) #define CC2420_SPI_IS_ENABLED() ((CC2420_CSN_PORT(OUT) & BV(CC2420_CSN_PIN)) != BV(CC2420_CSN_PIN)) -#endif /* PLATFORM_CONF_H_ */ +/* Platform-specific define for the end of the stack region */ +#define STACK_CONF_ORIGIN ((void *)0x3900) + +#endif /* SKY_DEF_H_ */ diff --git a/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx b/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx index 393cb62863d90bcf543375e2ffadd98bb8491dcd..db4209adc4d13ca078165c788b79e18fb22ba391 100644 --- a/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx +++ b/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx @@ -6,7 +6,7 @@ endif ### Board and BSP selection BOARD ?= srf06/cc26xx -BOARDS = srf06/cc26xx srf06/cc13xx launchpad/cc26xx launchpad/cc13xx sensortag/cc26xx sensortag/cc13xx +BOARDS = srf06/cc26xx srf06/cc13xx launchpad/cc2650 launchpad/cc1310 launchpad/cc1350 sensortag/cc2650 sensortag/cc1350 CONTIKI_TARGET_DIRS += . @@ -14,14 +14,11 @@ CONTIKI_TARGET_DIRS += . PLATFORM_ROOT_DIR = $(CONTIKI)/arch/platform/$(TARGET) -include $(PLATFORM_ROOT_DIR)/$(BOARD)/Makefile.$(notdir $(BOARD)) -CONTIKI_TARGET_SOURCEFILES += platform.c -CONTIKI_TARGET_SOURCEFILES += sensors.c leds.c +CONTIKI_TARGET_SOURCEFILES += platform.c leds-arch.c CONTIKI_TARGET_SOURCEFILES += $(BOARD_SOURCEFILES) CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) -CLEAN += *.srf06-cc26xx - ### Unless the example dictates otherwise, build without code size optimisations SMALL ?= 0 @@ -30,5 +27,3 @@ SMALL ?= 0 ### Makefile.cc26xx or Makefile.cc13xx CONTIKI_CPU=$(CONTIKI)/arch/cpu/cc26xx-cc13xx include $(CONTIKI_CPU)/Makefile.$(CPU_FAMILY) - -MODULES += os/net os/net/mac os/net/mac/framer diff --git a/arch/platform/srf06-cc26xx/cfs-coffee-arch.h b/arch/platform/srf06-cc26xx/cfs-coffee-arch.h new file mode 100644 index 0000000000000000000000000000000000000000..6816ca043bcd1ccbe3d90de6c7ce07129a79fe22 --- /dev/null +++ b/arch/platform/srf06-cc26xx/cfs-coffee-arch.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2008, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Coffee architecture-dependent header for the srf06-cc2650 sensortag platform. + * \author + * Dongda Lee <dongdongbhbh@gmail.com> + */ + +#ifndef CFS_COFFEE_ARCH_H +#define CFS_COFFEE_ARCH_H + +#include "contiki-conf.h" +#include "dev/xmem.h" + +/* + * MX25R8035F Memory Organization + * The memory is organized as: + * 8Mbit = 1048576 bytes (8 bits each) + * 256 sectors (32 Kbits, 4096 bytes each) + * 4096 pages (256 bytes each). + * Each page can be individually programmed (bits are programmed from 1 to 0). + * The device is sector or bulk erasable (bits are erased from 0 to 1) but not + * page erasable + */ +#define COFFEE_XMEM_TOTAL_SIZE_KB 1024UL /* Total size of the External Flash Memory in the Z1 */ + +/* Coffee configuration parameters. */ +#define COFFEE_SECTOR_SIZE 4096UL +#define COFFEE_PAGE_SIZE 256UL +#define COFFEE_START 0UL /* COFFEE_SECTOR_SIZE */ +#define COFFEE_SIZE (COFFEE_XMEM_TOTAL_SIZE_KB * 1024UL - COFFEE_START) +#define COFFEE_NAME_LENGTH 16 +#define COFFEE_MAX_OPEN_FILES 6 +#define COFFEE_FD_SET_SIZE 8 +#define COFFEE_LOG_TABLE_LIMIT 256 +#define COFFEE_DYN_SIZE 2 * 1024 +#define COFFEE_LOG_SIZE 1024 + +#define COFFEE_MICRO_LOGS 1 + +/* Flash operations. */ +#define COFFEE_WRITE(buf, size, offset) \ + xmem_pwrite((char *)(buf), (size), COFFEE_START + (offset)) + +#define COFFEE_READ(buf, size, offset) \ + xmem_pread((char *)(buf), (size), COFFEE_START + (offset)) + +#define COFFEE_ERASE(sector) \ + xmem_erase(COFFEE_SECTOR_SIZE, COFFEE_START + (sector) * COFFEE_SECTOR_SIZE) + +/* Coffee types. */ +typedef int16_t coffee_page_t; + +#endif /* !COFFEE_ARCH_H */ diff --git a/arch/platform/srf06-cc26xx/common/board-spi.c b/arch/platform/srf06-cc26xx/common/board-spi.c deleted file mode 100644 index fb9fecd638e69dee561488c1ccce47108226bef1..0000000000000000000000000000000000000000 --- a/arch/platform/srf06-cc26xx/common/board-spi.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/*---------------------------------------------------------------------------*/ -/** - * \addtogroup sensortag-cc26xx-spi - * @{ - * - * \file - * Board-specific SPI driver common to the Sensortag and LaunchPad - */ -/*---------------------------------------------------------------------------*/ -#include "contiki.h" -#include "ti-lib.h" -#include "board-spi.h" -#include "board.h" - -#include <stdbool.h> -/*---------------------------------------------------------------------------*/ -static bool -accessible(void) -{ - /* First, check the PD */ - if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) - != PRCM_DOMAIN_POWER_ON) { - return false; - } - - /* Then check the 'run mode' clock gate */ - if(!(HWREG(PRCM_BASE + PRCM_O_SSICLKGR) & PRCM_SSICLKGR_CLK_EN_SSI0)) { - return false; - } - - return true; -} -/*---------------------------------------------------------------------------*/ -bool -board_spi_write(const uint8_t *buf, size_t len) -{ - if(accessible() == false) { - return false; - } - - while(len > 0) { - uint32_t ul; - - ti_lib_ssi_data_put(SSI0_BASE, *buf); - ti_lib_rom_ssi_data_get(SSI0_BASE, &ul); - len--; - buf++; - } - - return true; -} -/*---------------------------------------------------------------------------*/ -bool -board_spi_read(uint8_t *buf, size_t len) -{ - if(accessible() == false) { - return false; - } - - while(len > 0) { - uint32_t ul; - - if(!ti_lib_rom_ssi_data_put_non_blocking(SSI0_BASE, 0)) { - /* Error */ - return false; - } - ti_lib_rom_ssi_data_get(SSI0_BASE, &ul); - *buf = (uint8_t)ul; - len--; - buf++; - } - return true; -} -/*---------------------------------------------------------------------------*/ -void -board_spi_flush() -{ - if(accessible() == false) { - return; - } - - uint32_t ul; - while(ti_lib_rom_ssi_data_get_non_blocking(SSI0_BASE, &ul)); -} -/*---------------------------------------------------------------------------*/ -void -board_spi_open(uint32_t bit_rate, uint32_t clk_pin) -{ - uint32_t buf; - - /* First, make sure the SERIAL PD is on */ - ti_lib_prcm_power_domain_on(PRCM_DOMAIN_SERIAL); - while((ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) - != PRCM_DOMAIN_POWER_ON)); - - /* Enable clock in active mode */ - ti_lib_rom_prcm_peripheral_run_enable(PRCM_PERIPH_SSI0); - ti_lib_prcm_load_set(); - while(!ti_lib_prcm_load_get()); - - /* SPI configuration */ - ti_lib_ssi_int_disable(SSI0_BASE, SSI_RXOR | SSI_RXFF | SSI_RXTO | SSI_TXFF); - ti_lib_ssi_int_clear(SSI0_BASE, SSI_RXOR | SSI_RXTO); - ti_lib_rom_ssi_config_set_exp_clk(SSI0_BASE, ti_lib_sys_ctrl_clock_get(), - SSI_FRF_MOTO_MODE_0, - SSI_MODE_MASTER, bit_rate, 8); - ti_lib_rom_ioc_pin_type_ssi_master(SSI0_BASE, BOARD_IOID_SPI_MISO, - BOARD_IOID_SPI_MOSI, IOID_UNUSED, clk_pin); - ti_lib_ssi_enable(SSI0_BASE); - - /* Get rid of residual data from SSI port */ - while(ti_lib_ssi_data_get_non_blocking(SSI0_BASE, &buf)); -} -/*---------------------------------------------------------------------------*/ -void -board_spi_close() -{ - /* Power down SSI0 */ - ti_lib_rom_prcm_peripheral_run_disable(PRCM_PERIPH_SSI0); - ti_lib_prcm_load_set(); - while(!ti_lib_prcm_load_get()); - - /* Restore pins to a low-consumption state */ - ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SPI_MISO); - ti_lib_ioc_io_port_pull_set(BOARD_IOID_SPI_MISO, IOC_IOPULL_DOWN); - - ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SPI_MOSI); - ti_lib_ioc_io_port_pull_set(BOARD_IOID_SPI_MOSI, IOC_IOPULL_DOWN); - - ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SPI_CLK_FLASH); - ti_lib_ioc_io_port_pull_set(BOARD_IOID_SPI_CLK_FLASH, IOC_IOPULL_DOWN); -} -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/srf06-cc26xx/common/board-spi.h b/arch/platform/srf06-cc26xx/common/board-spi.h deleted file mode 100644 index 3699db12077b0022d959e1aa115df00d454ee4e6..0000000000000000000000000000000000000000 --- a/arch/platform/srf06-cc26xx/common/board-spi.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/*---------------------------------------------------------------------------*/ -/** - * \addtogroup cc26xx-srf-tag - * @{ - * - * \defgroup common-cc26xx-peripherals CC13xx/CC26xx peripheral driver pool - * - * Drivers for peripherals present on more than one CC13xx/CC26xx board. For - * example, the same external flash driver is used for both the part found on - * the Sensortag as well as the part on the LaunchPad. - * - * @{ - * - * \defgroup sensortag-cc26xx-spi SensorTag/LaunchPad SPI functions - * @{ - * - * \file - * Header file for the Sensortag/LaunchPad SPI Driver - */ -/*---------------------------------------------------------------------------*/ -#ifndef BOARD_SPI_H_ -#define BOARD_SPI_H_ -/*---------------------------------------------------------------------------*/ -#include <stdlib.h> -#include <stdint.h> -#include <stdbool.h> -/*---------------------------------------------------------------------------*/ -/** - * \brief Initialize the SPI interface - * \param bit_rate The bit rate to use - * \param clk_pin The IOID for the clock pin. This can be IOID_0 etc - * \return none - * - * This function will make sure the peripheral is powered, clocked and - * initialised. A chain of calls to board_spi_read(), board_spi_write() and - * board_spi_flush() must be preceded by a call to this function. It is - * recommended to call board_spi_close() after such chain of calls. - */ -void board_spi_open(uint32_t bit_rate, uint32_t clk_pin); - -/** - * \brief Close the SPI interface - * \return True when successful. - * - * This function will stop clocks to the SSI module and will set MISO, MOSI - * and CLK to a low leakage state. It is recommended to call this function - * after a chain of calls to board_spi_read() and board_spi_write() - */ -void board_spi_close(void); - -/** - * \brief Clear data from the SPI interface - * \return none - */ -void board_spi_flush(void); - -/** - * \brief Read from an SPI device - * \param buf The buffer to store data - * \param length The number of bytes to read - * \return True when successful. - * - * Calls to this function must be preceded by a call to board_spi_open(). It is - * recommended to call board_spi_close() at the end of an operation. - */ -bool board_spi_read(uint8_t *buf, size_t length); - -/** - * \brief Write to an SPI device - * \param buf The buffer with the data to write - * \param length The number of bytes to write - * \return True when successful. - * - * Calls to this function must be preceded by a call to board_spi_open(). It is - * recommended to call board_spi_close() at the end of an operation. - */ -bool board_spi_write(const uint8_t *buf, size_t length); -/*---------------------------------------------------------------------------*/ -#endif /* BOARD_SPI_H_ */ -/*---------------------------------------------------------------------------*/ -/** - * @} - * @} - * @} - */ diff --git a/arch/platform/srf06-cc26xx/common/xmem.c b/arch/platform/srf06-cc26xx/common/xmem.c new file mode 100644 index 0000000000000000000000000000000000000000..9228e0fbbf8b2afecc38a4971c683f96762d2f58 --- /dev/null +++ b/arch/platform/srf06-cc26xx/common/xmem.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2006, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \file + * Device driver for the MX25R8035F 1Mbyte external memory. + * \author + * Dongda Lee <dongdongbhbh@gmail.com> + * + * Data is written bit inverted (~-operator) to flash so that + * unwritten data will read as zeros (UNIX style). + */ + +#include "contiki.h" +#include "ext-flash.h" +#include "dev/xmem.h" +#include "dev/watchdog.h" +#include "cfs-coffee-arch.h" +#include <stdio.h> /* For PRINTF() */ + +#define EXT_ERASE_UNIT_SIZE 4096UL + +#define XMEM_BUFF_LENGHT 128 + +#if 0 +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) do {} while(0) +#endif + +void +xmem_init(void) +{ + ext_flash_open(NULL); +} +int +xmem_pread(void *_p, int size, unsigned long addr) +{ + int rv; + uint8_t x; + int i; + + rv = ext_flash_open(NULL); + + if(!rv) { + PRINTF("Could not open flash to save config\n"); + ext_flash_close(NULL); + return -1; + } + + rv = ext_flash_read(NULL, addr, size, _p); + for(i = 0; i < size; i++) { + x = ~*((uint8_t *)_p + i); + *((uint8_t *)_p + i) = x; + } + + ext_flash_close(NULL); + + if(rv) { + return size; + } + + PRINTF("Could not read flash memory!\n"); + return -1; +} +int +xmem_pwrite(const void *_buf, int size, unsigned long addr) +{ + int rv; + int i, j; + int remain; + + uint8_t tmp_buf[XMEM_BUFF_LENGHT]; + + rv = ext_flash_open(NULL); + + if(!rv) { + PRINTF("Could not open flash to save config!\n"); + ext_flash_close(NULL); + return -1; + } + + for(remain = size, j = 0; remain > 0; remain -= XMEM_BUFF_LENGHT, j += XMEM_BUFF_LENGHT) { + int to_write = MIN(XMEM_BUFF_LENGHT, remain); + for(i = 0; i < to_write; i++) { + tmp_buf[i] = ~*((uint8_t *)_buf + j + i); + } + rv = ext_flash_write(NULL, addr + j, to_write, tmp_buf); + if(!rv) { + PRINTF("Could not write flash memory!\n"); + return size - remain; + } + } + + ext_flash_close(NULL); + + return size; +} +int +xmem_erase(long size, unsigned long addr) +{ + int rv; + + rv = ext_flash_open(NULL); + + if(!rv) { + PRINTF("Could not open flash to save config\n"); + ext_flash_close(NULL); + return -1; + } + + if(size % EXT_ERASE_UNIT_SIZE != 0) { + PRINTF("xmem_erase: bad size\n"); + return -1; + } + + if(addr % EXT_ERASE_UNIT_SIZE != 0) { + PRINTF("xmem_erase: bad offset\n"); + return -1; + } + + rv = ext_flash_erase(NULL, addr, size); + + ext_flash_close(NULL); + + watchdog_periodic(); + + if(rv) { + return size; + } + + PRINTF("Could not erase flash memory\n"); + return -1; +} diff --git a/arch/platform/srf06-cc26xx/contiki-conf.h b/arch/platform/srf06-cc26xx/contiki-conf.h index 3c7430c6ce6239bfb32df6aee6603cf311a861dd..4a1470b4025f7b306dc35facf214b9b77cd70d88 100644 --- a/arch/platform/srf06-cc26xx/contiki-conf.h +++ b/arch/platform/srf06-cc26xx/contiki-conf.h @@ -38,157 +38,14 @@ #define CONTIKI_CONF_H #include <stdint.h> +#include <inttypes.h> /*---------------------------------------------------------------------------*/ /* Include Project Specific conf */ #ifdef PROJECT_CONF_PATH #include PROJECT_CONF_PATH #endif /* PROJECT_CONF_PATH */ /*---------------------------------------------------------------------------*/ -/** - * \name Network Stack Configuration - * - * @{ - */ - -/* - * If set, the systems keeps the HF crystal oscillator on even when the radio is off. - * You need to set this to 1 to use TSCH with its default 2.2ms or larger guard time. - */ -#ifndef CC2650_FAST_RADIO_STARTUP -#define CC2650_FAST_RADIO_STARTUP (MAC_CONF_WITH_TSCH) -#endif - -#ifdef RF_CHANNEL -#define RF_CORE_CONF_CHANNEL RF_CHANNEL -#endif - -#ifndef RF_CORE_CONF_CHANNEL -#define RF_CORE_CONF_CHANNEL 25 -#endif - -/* Number of Prop Mode RX buffers */ -#ifndef PROP_MODE_CONF_RX_BUF_CNT -#define PROP_MODE_CONF_RX_BUF_CNT 4 -#endif - -/* - * Auto-configure Prop-mode radio if we are running on CC13xx, unless the - * project has specified otherwise. Depending on the final mode, determine a - * default channel (again, if unspecified) and configure RDC params - */ -#if CPU_FAMILY_CC13XX -#ifndef CC13XX_CONF_PROP_MODE -#define CC13XX_CONF_PROP_MODE 1 -#endif /* CC13XX_CONF_PROP_MODE */ -#endif /* CPU_FAMILY_CC13XX */ - -#if CC13XX_CONF_PROP_MODE -#define NETSTACK_CONF_RADIO prop_mode_driver - -#ifndef RF_CORE_CONF_CHANNEL -#define RF_CORE_CONF_CHANNEL 0 -#endif - -#define CSMA_CONF_ACK_WAIT_TIME (RTIMER_SECOND / 400) -#define CSMA_CONF_AFTER_ACK_DETECTED_WAIT_TIME (RTIMER_SECOND / 1000) -#define CSMA_CONF_SEND_SOFT_ACK 1 - -#else /* CC13XX_CONF_PROP_MODE */ -#define NETSTACK_CONF_RADIO ieee_mode_driver - -#define CSMA_CONF_SEND_SOFT_ACK 0 -#endif /* CC13XX_CONF_PROP_MODE */ - -#define NETSTACK_RADIO_MAX_PAYLOAD_LEN 125 - -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name IEEE address configuration - * - * Used to generate our link-local & IPv6 address - * @{ - */ -/** - * \brief Location of the IEEE address - * 0 => Read from InfoPage, - * 1 => Use a hardcoded address, configured by IEEE_ADDR_CONF_ADDRESS - */ -#ifndef IEEE_ADDR_CONF_HARDCODED -#define IEEE_ADDR_CONF_HARDCODED 0 -#endif - -/** - * \brief The hardcoded IEEE address to be used when IEEE_ADDR_CONF_HARDCODED - * is defined as 1 - */ -#ifndef IEEE_ADDR_CONF_ADDRESS -#define IEEE_ADDR_CONF_ADDRESS { 0x00, 0x12, 0x4B, 0x00, 0x89, 0xAB, 0xCD, 0xEF } -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name RF configuration - * - * @{ - */ -/* RF Config */ - -#ifndef IEEE_MODE_CONF_AUTOACK -#define IEEE_MODE_CONF_AUTOACK 1 /**< RF H/W generates ACKs */ -#endif - -#ifndef IEEE_MODE_CONF_PROMISCOUS -#define IEEE_MODE_CONF_PROMISCOUS 0 /**< 1 to enable promiscous mode */ -#endif - -#ifndef RF_BLE_CONF_ENABLED -#define RF_BLE_CONF_ENABLED 0 /**< 0 to disable BLE support */ -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name Character I/O Configuration - * - * @{ - */ -#ifndef CC26XX_UART_CONF_ENABLE -#define CC26XX_UART_CONF_ENABLE 1 /**< Enable/Disable UART I/O */ -#endif - -#ifndef CC26XX_UART_CONF_BAUD_RATE -#define CC26XX_UART_CONF_BAUD_RATE 115200 /**< Default UART0 baud rate */ -#endif - -/* Enable I/O over the Debugger Devpack - Only relevant for the SensorTag */ -#ifndef BOARD_CONF_DEBUGGER_DEVPACK -#define BOARD_CONF_DEBUGGER_DEVPACK 1 -#endif - -#ifndef SLIP_ARCH_CONF_ENABLED -/* - * Determine whether we need SLIP - * This will keep working while UIP_FALLBACK_INTERFACE and CMD_CONF_OUTPUT - * keep using SLIP - */ -#if defined(UIP_FALLBACK_INTERFACE) || defined(CMD_CONF_OUTPUT) -#define SLIP_ARCH_CONF_ENABLED 1 -#endif -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name ROM Bootloader configuration - * - * Enable/Disable the ROM bootloader in your image, if the board supports it. - * Look in board.h to choose the DIO and corresponding level that will cause - * the chip to enter bootloader mode. - * @{ - */ -#ifndef ROM_BOOTLOADER_ENABLE -#define ROM_BOOTLOADER_ENABLE 0 -#endif -/** @} */ +#include "cc13xx-cc26xx-def.h" /*---------------------------------------------------------------------------*/ /** * \name Button configurations @@ -202,6 +59,7 @@ /* Notify various examples that we have Buttons */ #define PLATFORM_HAS_BUTTON 1 +#define PLATFORM_SUPPORTS_BUTTON_HAL 1 /* * Override button symbols from dev/button-sensor.h, for the examples that @@ -214,91 +72,8 @@ /* Platform-specific define to signify sensor reading failure */ #define CC26XX_SENSOR_READING_ERROR 0x80000000 /*---------------------------------------------------------------------------*/ -/** - * \name Compiler configuration and platform-specific type definitions - * - * Those values are not meant to be modified by the user - * @{ - */ -#define CLOCK_CONF_SECOND 128 - -/* Compiler configurations */ -#define CCIF -#define CLIF - -/* Platform typedefs */ -typedef uint32_t clock_time_t; -typedef uint32_t uip_stats_t; - -/* Clock (time) comparison macro */ -#define CLOCK_LT(a, b) ((signed long)((a) - (b)) < 0) - -/* - * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define - * RTIMER_CLOCK_DIFF to override this - */ -typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_DIFF(a, b) ((int32_t)((a) - (b))) - -/* --------------------------------------------------------------------- */ -/* TSCH related defines */ - -/* Delay between GO signal and SFD */ -#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(81)) -/* Delay between GO signal and start listening. - * This value is so small because the radio is constantly on within each timeslot. */ -#define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(15)) -/* Delay between the SFD finishes arriving and it is detected in software. */ -#define RADIO_DELAY_BEFORE_DETECT ((unsigned)US_TO_RTIMERTICKS(352)) - -/* Timer conversion; radio is running at 4 MHz */ -#define RADIO_TIMER_SECOND 4000000u -#if (RTIMER_SECOND % 256) || (RADIO_TIMER_SECOND % 256) -#error RADIO_TO_RTIMER macro must be fixed! -#endif -#define RADIO_TO_RTIMER(X) ((uint32_t)(((uint64_t)(X) * (RTIMER_SECOND / 256)) / (RADIO_TIMER_SECOND / 256))) -#define USEC_TO_RADIO(X) ((X) * 4) - -/* The PHY header (preamble + SFD, 4+1 bytes) duration is equivalent to 10 symbols */ -#define RADIO_IEEE_802154_PHY_HEADER_DURATION_USEC 160 - -/* Do not turn off TSCH within a timeslot: not enough time */ -#define TSCH_CONF_RADIO_ON_DURING_TIMESLOT 1 - -/* Disable TSCH frame filtering */ -#define TSCH_CONF_HW_FRAME_FILTERING 0 - -/* Use hardware timestamps */ -#ifndef TSCH_CONF_RESYNC_WITH_SFD_TIMESTAMPS -#define TSCH_CONF_RESYNC_WITH_SFD_TIMESTAMPS 1 -#define TSCH_CONF_TIMESYNC_REMOVE_JITTER 0 -#endif - -#ifndef TSCH_CONF_BASE_DRIFT_PPM -/* The drift compared to "true" 10ms slots. - * Enable adaptive sync to enable compensation for this. - * Slot length 10000 usec - * 328 ticks - * Tick duration 30.517578125 usec - * Real slot duration 10009.765625 usec - * Target - real duration = -9.765625 usec - * TSCH_CONF_BASE_DRIFT_PPM -977 - */ -#define TSCH_CONF_BASE_DRIFT_PPM -977 -#endif - -/* 10 times per second */ -#ifndef TSCH_CONF_CHANNEL_SCAN_DURATION -#define TSCH_CONF_CHANNEL_SCAN_DURATION (CLOCK_SECOND / 10) -#endif - -/* Slightly reduce the TSCH guard time (from 2200 usec to 1800 usec) to make sure - * the CC26xx radio has sufficient time to start up. */ -#ifndef TSCH_CONF_RX_WAIT -#define TSCH_CONF_RX_WAIT 1800 -#endif - -/** @} */ +/* Include CPU-related configuration */ +#include "cc13xx-cc26xx-conf.h" /*---------------------------------------------------------------------------*/ /* board.h assumes that basic configuration is done */ #include "board.h" diff --git a/arch/platform/srf06-cc26xx/launchpad/Makefile.launchpad b/arch/platform/srf06-cc26xx/launchpad/Makefile.launchpad index 54bd81ced3b2eb7822c9d83ae6036105cf6422e2..09af79c0b3426ee63c54061161975204ebb0c17e 100644 --- a/arch/platform/srf06-cc26xx/launchpad/Makefile.launchpad +++ b/arch/platform/srf06-cc26xx/launchpad/Makefile.launchpad @@ -2,8 +2,9 @@ CFLAGS += -DBOARD_LAUNCHPAD=1 CONTIKI_TARGET_DIRS += launchpad common -BOARD_SOURCEFILES += board.c launchpad-sensors.c leds-arch.c button-sensor.c -BOARD_SOURCEFILES += ext-flash.c board-spi.c +BOARD_SOURCEFILES += board.c board-buttons.c xmem.c + +MODULES += arch/dev/ext-flash ### Signal that we can be programmed with cc2538-bsl BOARD_SUPPORTS_BSL=1 diff --git a/arch/platform/srf06-cc26xx/launchpad/board-buttons.c b/arch/platform/srf06-cc26xx/launchpad/board-buttons.c new file mode 100644 index 0000000000000000000000000000000000000000..f07fff09ebbb1dea36ad99c317562f8a8edc24a5 --- /dev/null +++ b/arch/platform/srf06-cc26xx/launchpad/board-buttons.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup launchpad-cc26xx-peripherals + * @{ + * + * \file + * Defines CC13xx/CC26xx Launchpad buttons for use with the button HAL + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/button-hal.h" + +#include "ti-lib.h" +/*---------------------------------------------------------------------------*/ +BUTTON_HAL_BUTTON(key_left, "Key Left", BOARD_IOID_KEY_LEFT, \ + GPIO_HAL_PIN_CFG_PULL_UP, BOARD_BUTTON_HAL_INDEX_KEY_LEFT, \ + true); + +BUTTON_HAL_BUTTON(key_right, "Key Right", BOARD_IOID_KEY_RIGHT, \ + GPIO_HAL_PIN_CFG_PULL_UP, BOARD_BUTTON_HAL_INDEX_KEY_RIGHT, \ + true); +/*---------------------------------------------------------------------------*/ +BUTTON_HAL_BUTTONS(&key_left, &key_right); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/arch/platform/srf06-cc26xx/launchpad/board-peripherals.h b/arch/platform/srf06-cc26xx/launchpad/board-peripherals.h index 3e122023468c0d235d3a414eaba483a23c739264..0ad9c6b68452e4295c9c18163154abd9c3047795 100644 --- a/arch/platform/srf06-cc26xx/launchpad/board-peripherals.h +++ b/arch/platform/srf06-cc26xx/launchpad/board-peripherals.h @@ -48,6 +48,8 @@ /*---------------------------------------------------------------------------*/ #include "ext-flash.h" /*---------------------------------------------------------------------------*/ +#define BOARD_CONF_HAS_SENSORS 0 +/*---------------------------------------------------------------------------*/ #endif /* BOARD_PERIPHERALS_H_ */ /*---------------------------------------------------------------------------*/ /** diff --git a/arch/platform/srf06-cc26xx/launchpad/board.c b/arch/platform/srf06-cc26xx/launchpad/board.c index 74b12bd3d5606d8fab4f3d2aa81a6bf3f632ca4c..cda0a7c6c69f273d81046fcba812926e3c9bdbd9 100644 --- a/arch/platform/srf06-cc26xx/launchpad/board.c +++ b/arch/platform/srf06-cc26xx/launchpad/board.c @@ -37,7 +37,6 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "lib/sensors.h" #include "lpm.h" #include "ti-lib.h" #include "board-peripherals.h" @@ -94,7 +93,7 @@ board_init() while(!ti_lib_prcm_load_get()); /* Make sure the external flash is in the lower power mode */ - ext_flash_init(); + ext_flash_init(NULL); lpm_register_module(&launchpad_module); diff --git a/arch/platform/srf06-cc26xx/launchpad/button-sensor.c b/arch/platform/srf06-cc26xx/launchpad/button-sensor.c deleted file mode 100644 index eb8bd3033fd8cd955490fa4d1c31b605060a674d..0000000000000000000000000000000000000000 --- a/arch/platform/srf06-cc26xx/launchpad/button-sensor.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/ - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/*---------------------------------------------------------------------------*/ -/** - * \addtogroup launchpad-button-sensor - * @{ - * - * \file - * Driver for LaunchPad buttons - */ -/*---------------------------------------------------------------------------*/ -#include "contiki.h" -#include "lib/sensors.h" -#include "launchpad/button-sensor.h" -#include "gpio-interrupt.h" -#include "sys/timer.h" -#include "lpm.h" - -#include "ti-lib.h" - -#include <stdint.h> -/*---------------------------------------------------------------------------*/ -#ifdef BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN -#define BUTTON_SENSOR_ENABLE_SHUTDOWN BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN -#else -#define BUTTON_SENSOR_ENABLE_SHUTDOWN 1 -#endif -/*---------------------------------------------------------------------------*/ -#define BUTTON_GPIO_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \ - IOC_IOPULL_UP | IOC_SLEW_DISABLE | \ - IOC_HYST_DISABLE | IOC_BOTH_EDGES | \ - IOC_INT_ENABLE | IOC_IOMODE_NORMAL | \ - IOC_NO_WAKE_UP | IOC_INPUT_ENABLE) -/*---------------------------------------------------------------------------*/ -#define DEBOUNCE_DURATION (CLOCK_SECOND >> 5) - -struct btn_timer { - struct timer debounce; - clock_time_t start; - clock_time_t duration; -}; - -static struct btn_timer left_timer, right_timer; -/*---------------------------------------------------------------------------*/ -static void -button_press_handler(uint8_t ioid) -{ - if(ioid == BOARD_IOID_KEY_LEFT) { - if(!timer_expired(&left_timer.debounce)) { - return; - } - - timer_set(&left_timer.debounce, DEBOUNCE_DURATION); - - /* - * Start press duration counter on press (falling), notify on release - * (rising) - */ - if(ti_lib_gpio_read_dio(BOARD_IOID_KEY_LEFT) == 0) { - left_timer.start = clock_time(); - left_timer.duration = 0; - } else { - left_timer.duration = clock_time() - left_timer.start; - sensors_changed(&button_left_sensor); - } - } - - if(ioid == BOARD_IOID_KEY_RIGHT) { - if(BUTTON_SENSOR_ENABLE_SHUTDOWN == 0) { - if(!timer_expired(&right_timer.debounce)) { - return; - } - - timer_set(&right_timer.debounce, DEBOUNCE_DURATION); - - /* - * Start press duration counter on press (falling), notify on release - * (rising) - */ - if(ti_lib_gpio_read_dio(BOARD_IOID_KEY_RIGHT) == 0) { - right_timer.start = clock_time(); - right_timer.duration = 0; - } else { - right_timer.duration = clock_time() - right_timer.start; - sensors_changed(&button_right_sensor); - } - } else { - lpm_shutdown(BOARD_IOID_KEY_RIGHT, IOC_IOPULL_UP, IOC_WAKE_ON_LOW); - } - } -} -/*---------------------------------------------------------------------------*/ -static void -config_buttons(int type, int c, uint32_t key) -{ - switch(type) { - case SENSORS_HW_INIT: - ti_lib_gpio_clear_event_dio(key); - ti_lib_rom_ioc_pin_type_gpio_input(key); - ti_lib_rom_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG); - gpio_interrupt_register_handler(key, button_press_handler); - break; - case SENSORS_ACTIVE: - if(c) { - ti_lib_gpio_clear_event_dio(key); - ti_lib_rom_ioc_pin_type_gpio_input(key); - ti_lib_rom_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG); - ti_lib_rom_ioc_int_enable(key); - } else { - ti_lib_rom_ioc_int_disable(key); - } - break; - default: - break; - } -} -/*---------------------------------------------------------------------------*/ -static int -config_left(int type, int value) -{ - config_buttons(type, value, BOARD_IOID_KEY_LEFT); - - return 1; -} -/*---------------------------------------------------------------------------*/ -static int -config_right(int type, int value) -{ - config_buttons(type, value, BOARD_IOID_KEY_RIGHT); - - return 1; -} -/*---------------------------------------------------------------------------*/ -static int -status(int type, uint32_t key_io_id) -{ - switch(type) { - case SENSORS_ACTIVE: - case SENSORS_READY: - if(ti_lib_rom_ioc_port_configure_get(key_io_id) & IOC_INT_ENABLE) { - return 1; - } - break; - default: - break; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -static int -value_left(int type) -{ - if(type == BUTTON_SENSOR_VALUE_STATE) { - return ti_lib_gpio_read_dio(BOARD_IOID_KEY_LEFT) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; - } else if(type == BUTTON_SENSOR_VALUE_DURATION) { - return (int)left_timer.duration; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -static int -value_right(int type) -{ - if(type == BUTTON_SENSOR_VALUE_STATE) { - return ti_lib_gpio_read_dio(BOARD_IOID_KEY_RIGHT) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; - } else if(type == BUTTON_SENSOR_VALUE_DURATION) { - return (int)right_timer.duration; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -static int -status_left(int type) -{ - return status(type, BOARD_IOID_KEY_LEFT); -} -/*---------------------------------------------------------------------------*/ -static int -status_right(int type) -{ - return status(type, BOARD_IOID_KEY_RIGHT); -} -/*---------------------------------------------------------------------------*/ -SENSORS_SENSOR(button_left_sensor, BUTTON_SENSOR, value_left, config_left, - status_left); -SENSORS_SENSOR(button_right_sensor, BUTTON_SENSOR, value_right, config_right, - status_right); -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/srf06-cc26xx/launchpad/cc1310/board.h b/arch/platform/srf06-cc26xx/launchpad/cc1310/board.h index a4b2efbbaa3f681ec6a3bb68760a6f615e4852c2..41e9295713d9e49c234e4e2c20179603ee5ab0e5 100644 --- a/arch/platform/srf06-cc26xx/launchpad/cc1310/board.h +++ b/arch/platform/srf06-cc26xx/launchpad/cc1310/board.h @@ -55,27 +55,14 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -/* Some files include leds.h before us, so we need to get rid of defaults in - * leds.h before we provide correct definitions */ -#undef LEDS_GREEN -#undef LEDS_YELLOW -#undef LEDS_RED -#undef LEDS_CONF_ALL - -#define LEDS_RED 1 -#define LEDS_GREEN 2 -#define LEDS_YELLOW LEDS_GREEN -#define LEDS_ORANGE LEDS_RED - -#define LEDS_CONF_ALL 3 - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 2 +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -86,9 +73,6 @@ */ #define BOARD_IOID_LED_1 IOID_6 #define BOARD_IOID_LED_2 IOID_7 -#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) -#define BOARD_LED_2 (1 << BOARD_IOID_LED_2) -#define BOARD_LED_ALL (BOARD_LED_1 | BOARD_LED_2) /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -119,25 +103,29 @@ #define BOARD_KEY_RIGHT (1 << BOARD_IOID_KEY_RIGHT) /** @} */ /*---------------------------------------------------------------------------*/ -/** - * \brief SPI IOID mappings - * - * Those values are not meant to be modified by the user - * @{ - */ -#define BOARD_IOID_SPI_MOSI IOID_9 -#define BOARD_IOID_SPI_MISO IOID_8 -/** @} */ -/*---------------------------------------------------------------------------*/ /** * \name External flash IOID mapping * * Those values are not meant to be modified by the user * @{ */ -#define BOARD_IOID_FLASH_CS IOID_20 -#define BOARD_FLASH_CS (1 << BOARD_IOID_FLASH_CS) -#define BOARD_IOID_SPI_CLK_FLASH IOID_10 +#define EXT_FLASH_SPI_CONTROLLER SPI_CONTROLLER_SPI0 + +#define BOARD_IOID_FLASH_SCK IOID_10 +#define BOARD_IOID_FLASH_MOSI IOID_9 +#define BOARD_IOID_FLASH_MISO IOID_8 +#define BOARD_IOID_FLASH_CS IOID_20 + +#define EXT_FLASH_SPI_PIN_SCK 10 +#define EXT_FLASH_SPI_PIN_MOSI 9 +#define EXT_FLASH_SPI_PIN_MISO 8 +#define EXT_FLASH_SPI_PIN_CS 20 + +#define EXT_FLASH_DEVICE_ID 0x14 +#define EXT_FLASH_MID 0xC2 + +#define EXT_FLASH_PROGRAM_PAGE_SIZE 256 +#define EXT_FLASH_ERASE_SECTOR_SIZE 4096 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -204,6 +192,16 @@ } /** @} */ /*---------------------------------------------------------------------------*/ +/** + * \brief Board indices for the button HAL + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_BUTTON_HAL_INDEX_KEY_LEFT 0x00 +#define BOARD_BUTTON_HAL_INDEX_KEY_RIGHT 0x01 +/** @} */ +/*---------------------------------------------------------------------------*/ /** * \name Device string used on startup * @{ diff --git a/arch/platform/srf06-cc26xx/launchpad/cc1350/board.h b/arch/platform/srf06-cc26xx/launchpad/cc1350/board.h index e645b8b0b00d87b7c0c26d3f44779efae0e6b1e9..643d69e0b4418ccb400afc97180565fd1e12b20a 100644 --- a/arch/platform/srf06-cc26xx/launchpad/cc1350/board.h +++ b/arch/platform/srf06-cc26xx/launchpad/cc1350/board.h @@ -55,27 +55,14 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -/* Some files include leds.h before us, so we need to get rid of defaults in - * leds.h before we provide correct definitions */ -#undef LEDS_GREEN -#undef LEDS_YELLOW -#undef LEDS_RED -#undef LEDS_CONF_ALL - -#define LEDS_RED 1 -#define LEDS_GREEN 2 -#define LEDS_YELLOW LEDS_GREEN -#define LEDS_ORANGE LEDS_RED - -#define LEDS_CONF_ALL 3 - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 2 +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -86,9 +73,6 @@ */ #define BOARD_IOID_LED_1 IOID_6 #define BOARD_IOID_LED_2 IOID_7 -#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) -#define BOARD_LED_2 (1 << BOARD_IOID_LED_2) -#define BOARD_LED_ALL (BOARD_LED_1 | BOARD_LED_2) /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -119,26 +103,29 @@ #define BOARD_KEY_RIGHT (1 << BOARD_IOID_KEY_RIGHT) /** @} */ /*---------------------------------------------------------------------------*/ -/** - * \brief SPI IOID mappings - * - * Those values are not meant to be modified by the user - * @{ - */ -#define BOARD_IOID_SPI_MOSI IOID_9 -#define BOARD_IOID_SPI_MISO IOID_8 -/** @} */ -/*---------------------------------------------------------------------------*/ /** * \name External flash IOID mapping * * Those values are not meant to be modified by the user * @{ */ -#define BOARD_IOID_FLASH_CS IOID_20 -#define BOARD_FLASH_CS (1 << BOARD_IOID_FLASH_CS) -#define BOARD_IOID_SPI_CLK_FLASH IOID_10 -/** @} */ +#define EXT_FLASH_SPI_CONTROLLER SPI_CONTROLLER_SPI0 + +#define BOARD_IOID_FLASH_SCK IOID_10 +#define BOARD_IOID_FLASH_MOSI IOID_9 +#define BOARD_IOID_FLASH_MISO IOID_8 +#define BOARD_IOID_FLASH_CS IOID_20 + +#define EXT_FLASH_SPI_PIN_SCK 10 +#define EXT_FLASH_SPI_PIN_MOSI 9 +#define EXT_FLASH_SPI_PIN_MISO 8 +#define EXT_FLASH_SPI_PIN_CS 20 + +#define EXT_FLASH_DEVICE_ID 0x14 +#define EXT_FLASH_MID 0xC2 + +#define EXT_FLASH_PROGRAM_PAGE_SIZE 256 +#define EXT_FLASH_ERASE_SECTOR_SIZE 4096 /*---------------------------------------------------------------------------*/ /** * \brief I2C IOID mappings @@ -221,6 +208,16 @@ } /** @} */ /*---------------------------------------------------------------------------*/ +/** + * \brief Board indices for the button HAL + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_BUTTON_HAL_INDEX_KEY_LEFT 0x00 +#define BOARD_BUTTON_HAL_INDEX_KEY_RIGHT 0x01 +/** @} */ +/*---------------------------------------------------------------------------*/ /** * \name Device string used on startup * @{ diff --git a/arch/platform/srf06-cc26xx/launchpad/cc2650/board.h b/arch/platform/srf06-cc26xx/launchpad/cc2650/board.h index 9b9d00bf022b1fde047881be75c22e776e2d9362..822e776b8792da0a532357f1a42a5609ef82ed90 100644 --- a/arch/platform/srf06-cc26xx/launchpad/cc2650/board.h +++ b/arch/platform/srf06-cc26xx/launchpad/cc2650/board.h @@ -55,27 +55,14 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -/* Some files include leds.h before us, so we need to get rid of defaults in - * leds.h before we provide correct definitions */ -#undef LEDS_GREEN -#undef LEDS_YELLOW -#undef LEDS_RED -#undef LEDS_CONF_ALL - -#define LEDS_RED 1 -#define LEDS_GREEN 2 -#define LEDS_YELLOW LEDS_GREEN -#define LEDS_ORANGE LEDS_RED - -#define LEDS_CONF_ALL 3 - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 2 +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -86,9 +73,6 @@ */ #define BOARD_IOID_LED_1 IOID_6 #define BOARD_IOID_LED_2 IOID_7 -#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) -#define BOARD_LED_2 (1 << BOARD_IOID_LED_2) -#define BOARD_LED_ALL (BOARD_LED_1 | BOARD_LED_2) /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -119,25 +103,29 @@ #define BOARD_KEY_RIGHT (1 << BOARD_IOID_KEY_RIGHT) /** @} */ /*---------------------------------------------------------------------------*/ -/** - * \brief SPI IOID mappings - * - * Those values are not meant to be modified by the user - * @{ - */ -#define BOARD_IOID_SPI_MOSI IOID_9 -#define BOARD_IOID_SPI_MISO IOID_8 -/** @} */ -/*---------------------------------------------------------------------------*/ /** * \name External flash IOID mapping * * Those values are not meant to be modified by the user * @{ */ -#define BOARD_IOID_FLASH_CS IOID_20 -#define BOARD_FLASH_CS (1 << BOARD_IOID_FLASH_CS) -#define BOARD_IOID_SPI_CLK_FLASH IOID_10 +#define EXT_FLASH_SPI_CONTROLLER SPI_CONTROLLER_SPI0 + +#define BOARD_IOID_FLASH_SCK IOID_10 +#define BOARD_IOID_FLASH_MOSI IOID_9 +#define BOARD_IOID_FLASH_MISO IOID_8 +#define BOARD_IOID_FLASH_CS IOID_20 + +#define EXT_FLASH_SPI_PIN_SCK 10 +#define EXT_FLASH_SPI_PIN_MOSI 9 +#define EXT_FLASH_SPI_PIN_MISO 8 +#define EXT_FLASH_SPI_PIN_CS 20 + +#define EXT_FLASH_DEVICE_ID 0x14 +#define EXT_FLASH_MID 0xC2 + +#define EXT_FLASH_PROGRAM_PAGE_SIZE 256 +#define EXT_FLASH_ERASE_SECTOR_SIZE 4096 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -205,6 +193,16 @@ } /** @} */ /*---------------------------------------------------------------------------*/ +/** + * \brief Board indices for the button HAL + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_BUTTON_HAL_INDEX_KEY_LEFT 0x00 +#define BOARD_BUTTON_HAL_INDEX_KEY_RIGHT 0x01 +/** @} */ +/*---------------------------------------------------------------------------*/ /** * \name Device string used on startup * @{ diff --git a/arch/platform/srf06-cc26xx/launchpad/leds-arch.c b/arch/platform/srf06-cc26xx/launchpad/leds-arch.c index 0d8385ad6d6a112f093f35ffa8a2f69a48f14a37..3c483d3bdd0a1f346b8a6628801ce3e0ec930640 100644 --- a/arch/platform/srf06-cc26xx/launchpad/leds-arch.c +++ b/arch/platform/srf06-cc26xx/launchpad/leds-arch.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright @@ -28,54 +29,15 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** - * \addtogroup launchpad-peripherals - * @{ - * - * \file - * Driver for LaunchPad LEDs - */ -/*---------------------------------------------------------------------------*/ #include "contiki.h" #include "dev/leds.h" - +#include "dev/gpio-hal.h" #include "ti-lib.h" -/*---------------------------------------------------------------------------*/ -static unsigned char c; -static int inited = 0; -/*---------------------------------------------------------------------------*/ -void -leds_arch_init(void) -{ - if(inited) { - return; - } - inited = 1; - - ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_LED_1); - ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_LED_2); - ti_lib_gpio_clear_multi_dio(BOARD_LED_ALL); -} +#include <stdbool.h> /*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - return c; -} -/*---------------------------------------------------------------------------*/ -void -leds_arch_set(unsigned char leds) -{ - c = leds; - ti_lib_gpio_clear_multi_dio(BOARD_LED_ALL); - - if((leds & LEDS_RED) == LEDS_RED) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_1); - } - if((leds & LEDS_YELLOW) == LEDS_YELLOW) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_2); - } -} +const leds_t leds_arch_leds[] = { + { .pin = BOARD_IOID_LED_1, .negative_logic = false }, + { .pin = BOARD_IOID_LED_2, .negative_logic = false }, +}; /*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/srf06-cc26xx/platform.c b/arch/platform/srf06-cc26xx/platform.c index 7b8a8c47790a3e10ad35037ea9e9e6c796f597ad..bfda15dadaad3ec94d70ddd651c41c277329ad72 100644 --- a/arch/platform/srf06-cc26xx/platform.c +++ b/arch/platform/srf06-cc26xx/platform.c @@ -47,14 +47,16 @@ #include "ti-lib.h" #include "contiki.h" #include "contiki-net.h" -#include "leds.h" #include "lpm.h" -#include "gpio-interrupt.h" +#include "dev/leds.h" +#include "dev/gpio-hal.h" #include "dev/oscillators.h" #include "ieee-addr.h" +#include "ble-addr.h" #include "vims.h" #include "dev/cc26xx-uart.h" #include "dev/soc-rtc.h" +#include "dev/serial-line.h" #include "rf-core/rf-core.h" #include "sys_ctrl.h" #include "uart.h" @@ -66,7 +68,9 @@ #include "lib/sensors.h" #include "button-sensor.h" #include "dev/serial-line.h" +#include "dev/button-hal.h" #include "net/mac/framer/frame802154.h" +#include "board-peripherals.h" #include "driverlib/driverlib_release.h" @@ -82,8 +86,14 @@ unsigned short node_id = 0; /** \brief Board specific iniatialisation */ void board_init(void); /*---------------------------------------------------------------------------*/ +#ifdef BOARD_CONF_HAS_SENSORS +#define BOARD_HAS_SENSORS BOARD_CONF_HAS_SENSORS +#else +#define BOARD_HAS_SENSORS 1 +#endif +/*---------------------------------------------------------------------------*/ static void -fade(unsigned char l) +fade(leds_mask_t l) { volatile int i; int k, j; @@ -104,9 +114,13 @@ fade(unsigned char l) static void set_rf_params(void) { - uint16_t short_addr; uint8_t ext_addr[8]; +#if MAC_CONF_WITH_BLE + ble_eui64_addr_cpy_to((uint8_t *)&ext_addr); + NETSTACK_RADIO.set_object(RADIO_PARAM_64BIT_ADDR, ext_addr, 8); +#else + uint16_t short_addr; ieee_addr_cpy_to(ext_addr, 8); short_addr = ext_addr[7]; @@ -119,6 +133,7 @@ set_rf_params(void) /* also set the global node id */ node_id = short_addr; +#endif } /*---------------------------------------------------------------------------*/ void @@ -137,7 +152,7 @@ platform_init_stage_one() board_init(); - gpio_interrupt_init(); + gpio_hal_init(); leds_init(); fade(LEDS_RED); @@ -150,6 +165,7 @@ platform_init_stage_one() */ ti_lib_pwr_ctrl_io_freeze_disable(); + ti_lib_rom_int_enable(INT_AON_GPIO_EDGE); ti_lib_int_master_enable(); soc_rtc_init(); @@ -168,8 +184,20 @@ platform_init_stage_two() serial_line_init(); +#if BUILD_WITH_SHELL + cc26xx_uart_set_input(serial_line_input_byte); +#endif + /* Populate linkaddr_node_addr */ +#if MAC_CONF_WITH_BLE + uint8_t ext_addr[8]; + ble_eui64_addr_cpy_to((uint8_t *)&ext_addr); + memcpy(&linkaddr_node_addr, &ext_addr[8 - LINKADDR_SIZE], LINKADDR_SIZE); +#else ieee_addr_cpy_to(linkaddr_node_addr.u8, LINKADDR_SIZE); +#endif + + button_hal_init(); fade(LEDS_GREEN); } @@ -177,12 +205,12 @@ platform_init_stage_two() void platform_init_stage_three() { - radio_value_t chan, pan; + radio_value_t chan = 0; + radio_value_t pan = 0; set_rf_params(); NETSTACK_RADIO.get_value(RADIO_PARAM_CHANNEL, &chan); - NETSTACK_RADIO.get_value(RADIO_PARAM_PAN_ID, &pan); LOG_DBG("With DriverLib v%u.%u\n", DRIVERLIB_RELEASE_GROUP, DRIVERLIB_RELEASE_BUILD); @@ -192,10 +220,19 @@ platform_init_stage_three() ti_lib_chipinfo_chip_family_is_cc13xx() == true ? "Yes" : "No", ti_lib_chipinfo_supports_ble() == true ? "Yes" : "No", ti_lib_chipinfo_supports_proprietary() == true ? "Yes" : "No"); - LOG_INFO(" RF: Channel %d, PANID 0x%04X\n", chan, pan); + LOG_INFO(" RF: Channel %d", chan); + + if(NETSTACK_RADIO.get_value(RADIO_PARAM_PAN_ID, &pan) == RADIO_RESULT_OK) { + LOG_INFO_(", PANID 0x%04X", pan); + } + LOG_INFO_("\n"); + LOG_INFO(" Node ID: %d\n", node_id); +#if BOARD_HAS_SENSORS process_start(&sensors_process, NULL); +#endif + fade(LEDS_ORANGE); } /*---------------------------------------------------------------------------*/ diff --git a/arch/platform/srf06-cc26xx/sensortag/Makefile.sensortag b/arch/platform/srf06-cc26xx/sensortag/Makefile.sensortag index 68e4b007fb083fa399dce4393ba37b267a5e4a16..5f7712fef944c897f1b62c2cfd0b551c4650a19e 100644 --- a/arch/platform/srf06-cc26xx/sensortag/Makefile.sensortag +++ b/arch/platform/srf06-cc26xx/sensortag/Makefile.sensortag @@ -3,8 +3,10 @@ CFLAGS += -DBACKDOOR_IOID=0x00000000 CONTIKI_TARGET_DIRS += sensortag common -BOARD_SOURCEFILES += sensortag-sensors.c sensor-common.c +BOARD_SOURCEFILES += sensortag-sensors.c board-buttons.c sensor-common.c BOARD_SOURCEFILES += bmp-280-sensor.c tmp-007-sensor.c opt-3001-sensor.c -BOARD_SOURCEFILES += hdc-1000-sensor.c mpu-9250-sensor.c button-sensor.c -BOARD_SOURCEFILES += reed-relay.c ext-flash.c buzzer.c -BOARD_SOURCEFILES += board.c board-spi.c board-i2c.c +BOARD_SOURCEFILES += hdc-1000-sensor.c mpu-9250-sensor.c xmem.c +BOARD_SOURCEFILES += buzzer.c +BOARD_SOURCEFILES += board.c board-i2c.c + +MODULES += arch/dev/ext-flash diff --git a/arch/platform/srf06-cc26xx/sensortag/board-buttons.c b/arch/platform/srf06-cc26xx/sensortag/board-buttons.c new file mode 100644 index 0000000000000000000000000000000000000000..4a1b02ed5134120c047ecb783ae9f2ce40a69ff6 --- /dev/null +++ b/arch/platform/srf06-cc26xx/sensortag/board-buttons.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup sensortag-cc26xx-peripherals + * @{ + * + * \file + * Defines Sensortag buttons for use with the button HAL + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +#include "dev/button-hal.h" + +#include "ti-lib.h" + +#include <stdbool.h> +/*---------------------------------------------------------------------------*/ +BUTTON_HAL_BUTTON(reed_relay, "Reed Relay", BOARD_IOID_REED_RELAY, \ + GPIO_HAL_PIN_CFG_PULL_DOWN, \ + BOARD_BUTTON_HAL_INDEX_REED_RELAY, true); + +BUTTON_HAL_BUTTON(key_left, "Key Left", BOARD_IOID_KEY_LEFT, \ + GPIO_HAL_PIN_CFG_PULL_UP, BOARD_BUTTON_HAL_INDEX_KEY_LEFT, \ + true); + +BUTTON_HAL_BUTTON(key_right, "Key Right", BOARD_IOID_KEY_RIGHT, \ + GPIO_HAL_PIN_CFG_PULL_UP, BOARD_BUTTON_HAL_INDEX_KEY_RIGHT, \ + true); +/*---------------------------------------------------------------------------*/ +BUTTON_HAL_BUTTONS(&reed_relay, &key_left, &key_right); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/arch/platform/srf06-cc26xx/sensortag/board-peripherals.h b/arch/platform/srf06-cc26xx/sensortag/board-peripherals.h index 42e22d4c88e59fe2683d7d22c10134d3c5cde55b..65c03198b7e29e04cb627a9867c194167dc0f6d9 100644 --- a/arch/platform/srf06-cc26xx/sensortag/board-peripherals.h +++ b/arch/platform/srf06-cc26xx/sensortag/board-peripherals.h @@ -53,7 +53,6 @@ #include "opt-3001-sensor.h" #include "hdc-1000-sensor.h" #include "mpu-9250-sensor.h" -#include "reed-relay.h" #include "buzzer.h" #include "ext-flash.h" /*---------------------------------------------------------------------------*/ diff --git a/arch/platform/srf06-cc26xx/sensortag/board.c b/arch/platform/srf06-cc26xx/sensortag/board.c index e2069f39f9affd0be734dd716afb68d1a9afebde..4b6a69bdebcc3e9070ffba5ca2cbc7dec018a726 100644 --- a/arch/platform/srf06-cc26xx/sensortag/board.c +++ b/arch/platform/srf06-cc26xx/sensortag/board.c @@ -146,7 +146,7 @@ board_init() buzzer_init(); /* Make sure the external flash is in the lower power mode */ - ext_flash_init(); + ext_flash_init(NULL); lpm_register_module(&sensortag_module); diff --git a/arch/platform/srf06-cc26xx/sensortag/button-sensor.c b/arch/platform/srf06-cc26xx/sensortag/button-sensor.c deleted file mode 100644 index 7ec0a5a18d23ce44d9fb3d37424e8cdc361bde94..0000000000000000000000000000000000000000 --- a/arch/platform/srf06-cc26xx/sensortag/button-sensor.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/*---------------------------------------------------------------------------*/ -/** - * \addtogroup sensortag-cc26xx-button-sensor - * @{ - * - * \file - * Driver for Sensortag buttons - */ -/*---------------------------------------------------------------------------*/ -#include "contiki.h" -#include "lib/sensors.h" -#include "sensortag/button-sensor.h" -#include "gpio-interrupt.h" -#include "sys/timer.h" -#include "lpm.h" - -#include "ti-lib.h" - -#include <stdint.h> -/*---------------------------------------------------------------------------*/ -#ifdef BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN -#define BUTTON_SENSOR_ENABLE_SHUTDOWN BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN -#else -#define BUTTON_SENSOR_ENABLE_SHUTDOWN 1 -#endif -/*---------------------------------------------------------------------------*/ -#define BUTTON_GPIO_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \ - IOC_IOPULL_UP | IOC_SLEW_DISABLE | \ - IOC_HYST_DISABLE | IOC_BOTH_EDGES | \ - IOC_INT_ENABLE | IOC_IOMODE_NORMAL | \ - IOC_NO_WAKE_UP | IOC_INPUT_ENABLE) -/*---------------------------------------------------------------------------*/ -#define DEBOUNCE_DURATION (CLOCK_SECOND >> 5) - -struct btn_timer { - struct timer debounce; - clock_time_t start; - clock_time_t duration; -}; - -static struct btn_timer left_timer, right_timer; -/*---------------------------------------------------------------------------*/ -/** - * \brief Handler for Sensortag-CC26XX button presses - */ -static void -button_press_handler(uint8_t ioid) -{ - if(ioid == BOARD_IOID_KEY_LEFT) { - if(!timer_expired(&left_timer.debounce)) { - return; - } - - timer_set(&left_timer.debounce, DEBOUNCE_DURATION); - - /* - * Start press duration counter on press (falling), notify on release - * (rising) - */ - if(ti_lib_gpio_read_dio(BOARD_IOID_KEY_LEFT) == 0) { - left_timer.start = clock_time(); - left_timer.duration = 0; - } else { - left_timer.duration = clock_time() - left_timer.start; - sensors_changed(&button_left_sensor); - } - } - - if(ioid == BOARD_IOID_KEY_RIGHT) { - if(BUTTON_SENSOR_ENABLE_SHUTDOWN == 0) { - if(!timer_expired(&right_timer.debounce)) { - return; - } - - timer_set(&right_timer.debounce, DEBOUNCE_DURATION); - - /* - * Start press duration counter on press (falling), notify on release - * (rising) - */ - if(ti_lib_gpio_read_dio(BOARD_IOID_KEY_RIGHT) == 0) { - right_timer.start = clock_time(); - right_timer.duration = 0; - } else { - right_timer.duration = clock_time() - right_timer.start; - sensors_changed(&button_right_sensor); - } - } else { - lpm_shutdown(BOARD_IOID_KEY_RIGHT, IOC_IOPULL_UP, IOC_WAKE_ON_LOW); - } - } -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Configuration function for the button sensor for all buttons. - * - * \param type This function does nothing unless type == SENSORS_ACTIVE - * \param c 0: disable the button, non-zero: enable - * \param key: One of BOARD_KEY_LEFT, BOARD_KEY_RIGHT etc - */ -static void -config_buttons(int type, int c, uint32_t key) -{ - switch(type) { - case SENSORS_HW_INIT: - ti_lib_gpio_clear_event_dio(key); - ti_lib_rom_ioc_pin_type_gpio_input(key); - ti_lib_rom_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG); - gpio_interrupt_register_handler(key, button_press_handler); - break; - case SENSORS_ACTIVE: - if(c) { - ti_lib_gpio_clear_event_dio(key); - ti_lib_rom_ioc_pin_type_gpio_input(key); - ti_lib_rom_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG); - ti_lib_rom_ioc_int_enable(key); - } else { - ti_lib_rom_ioc_int_disable(key); - } - break; - default: - break; - } -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Configuration function for the left button. - * - * Parameters are passed onto config_buttons, which does the actual - * configuration - * Parameters are ignored. They have been included because the prototype is - * dictated by the core sensor API. The return value is also required by - * the API but otherwise ignored. - * - * \param type passed to config_buttons as-is - * \param value passed to config_buttons as-is - * - * \return ignored - */ -static int -config_left(int type, int value) -{ - config_buttons(type, value, BOARD_IOID_KEY_LEFT); - - return 1; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Configuration function for the right button. - * - * Parameters are passed onto config_buttons, which does the actual - * configuration - * Parameters are ignored. They have been included because the prototype is - * dictated by the core sensor api. The return value is also required by - * the API but otherwise ignored. - * - * \param type passed to config_buttons as-is - * \param value passed to config_buttons as-is - * - * \return ignored - */ -static int -config_right(int type, int value) -{ - config_buttons(type, value, BOARD_IOID_KEY_RIGHT); - - return 1; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Status function for all buttons - * \param type SENSORS_ACTIVE or SENSORS_READY - * \param key_io_id BOARD_IOID_KEY_LEFT, BOARD_IOID_KEY_RIGHT etc - * \return 1 if the button's port interrupt is enabled (edge detect) - * - * This function will only be called by status_left, status_right and the - * called will pass the correct key_io_id - */ -static int -status(int type, uint32_t key_io_id) -{ - switch(type) { - case SENSORS_ACTIVE: - case SENSORS_READY: - if(ti_lib_ioc_port_configure_get(key_io_id) & IOC_INT_ENABLE) { - return 1; - } - break; - default: - break; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -static int -value_left(int type) -{ - if(type == BUTTON_SENSOR_VALUE_STATE) { - return ti_lib_gpio_read_dio(BOARD_IOID_KEY_LEFT) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; - } else if(type == BUTTON_SENSOR_VALUE_DURATION) { - return (int)left_timer.duration; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -static int -value_right(int type) -{ - if(type == BUTTON_SENSOR_VALUE_STATE) { - return ti_lib_gpio_read_dio(BOARD_IOID_KEY_RIGHT) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; - } else if(type == BUTTON_SENSOR_VALUE_DURATION) { - return (int)right_timer.duration; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Status function for the left button. - * \param type SENSORS_ACTIVE or SENSORS_READY - * \return 1 if the button's port interrupt is enabled (edge detect) - * - * This function will call status. It will pass type verbatim and it will also - * pass the correct key_io_id - */ -static int -status_left(int type) -{ - return status(type, BOARD_IOID_KEY_LEFT); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Status function for the right button. - * \param type SENSORS_ACTIVE or SENSORS_READY - * \return 1 if the button's port interrupt is enabled (edge detect) - * - * This function will call status. It will pass type verbatim and it will also - * pass the correct key_io_id - */ -static int -status_right(int type) -{ - return status(type, BOARD_IOID_KEY_RIGHT); -} -/*---------------------------------------------------------------------------*/ -SENSORS_SENSOR(button_left_sensor, BUTTON_SENSOR, value_left, config_left, - status_left); -SENSORS_SENSOR(button_right_sensor, BUTTON_SENSOR, value_right, config_right, - status_right); -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/srf06-cc26xx/sensortag/cc1350/Makefile.cc1350 b/arch/platform/srf06-cc26xx/sensortag/cc1350/Makefile.cc1350 index 3cacec19776a29d67b5422b1372560223da5d324..cdae4c2b1c85f846880b3f0b777f7fc3bc6a7800 100644 --- a/arch/platform/srf06-cc26xx/sensortag/cc1350/Makefile.cc1350 +++ b/arch/platform/srf06-cc26xx/sensortag/cc1350/Makefile.cc1350 @@ -1,6 +1,3 @@ -### Add to the source list -BOARD_SOURCEFILES += leds-arch.c - ### Will allow the inclusion of the correct CPU makefile CPU_FAMILY = cc13xx diff --git a/arch/platform/srf06-cc26xx/sensortag/cc1350/board.h b/arch/platform/srf06-cc26xx/sensortag/cc1350/board.h index 7db4c93579ada9a2663687a791a7066d35b2727d..6fdab12955f73f5abe77f870d1c17186a0742f18 100644 --- a/arch/platform/srf06-cc26xx/sensortag/cc1350/board.h +++ b/arch/platform/srf06-cc26xx/sensortag/cc1350/board.h @@ -58,27 +58,13 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -/* Some files include leds.h before us, so we need to get rid of defaults in - * leds.h before we provide correct definitions */ -#undef LEDS_GREEN -#undef LEDS_YELLOW -#undef LEDS_RED -#undef LEDS_CONF_ALL - -#define LEDS_RED 1 -#define LEDS_GREEN LEDS_RED -#define LEDS_YELLOW LEDS_RED -#define LEDS_ORANGE LEDS_RED - -#define LEDS_CONF_ALL 1 - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 1 +#define LEDS_CONF_RED 1 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -88,8 +74,6 @@ * @{ */ #define BOARD_IOID_LED_1 IOID_10 -#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) -#define BOARD_LED_ALL BOARD_LED_1 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -129,16 +113,6 @@ #define BOARD_KEY_RIGHT (1 << BOARD_IOID_KEY_RIGHT) /** @} */ /*---------------------------------------------------------------------------*/ -/** - * \brief SPI IOID mappings - * - * Those values are not meant to be modified by the user - * @{ - */ -#define BOARD_IOID_SPI_MOSI IOID_19 -#define BOARD_IOID_SPI_MISO IOID_18 -/** @} */ -/*---------------------------------------------------------------------------*/ /** * \name Buzzer configuration * @{ @@ -161,9 +135,23 @@ * Those values are not meant to be modified by the user * @{ */ -#define BOARD_IOID_FLASH_CS IOID_14 -#define BOARD_FLASH_CS (1 << BOARD_IOID_FLASH_CS) -#define BOARD_IOID_SPI_CLK_FLASH IOID_17 +#define EXT_FLASH_SPI_CONTROLLER SPI_CONTROLLER_SPI0 + +#define BOARD_IOID_FLASH_SCK IOID_17 +#define BOARD_IOID_FLASH_MOSI IOID_19 +#define BOARD_IOID_FLASH_MISO IOID_18 +#define BOARD_IOID_FLASH_CS IOID_14 + +#define EXT_FLASH_SPI_PIN_SCK 17 +#define EXT_FLASH_SPI_PIN_MOSI 19 +#define EXT_FLASH_SPI_PIN_MISO 18 +#define EXT_FLASH_SPI_PIN_CS 14 + +#define EXT_FLASH_DEVICE_ID 0x14 +#define EXT_FLASH_MID 0xC2 + +#define EXT_FLASH_PROGRAM_PAGE_SIZE 256 +#define EXT_FLASH_ERASE_SECTOR_SIZE 4096 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -254,6 +242,17 @@ #define SMARTRF_SETTINGS_CONF_OVERRIDE_TRIM_OFFSET 0x00018883 /** @} */ /*---------------------------------------------------------------------------*/ +/** + * \brief Board indices for the button HAL + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_BUTTON_HAL_INDEX_KEY_LEFT 0x00 +#define BOARD_BUTTON_HAL_INDEX_KEY_RIGHT 0x01 +#define BOARD_BUTTON_HAL_INDEX_REED_RELAY 0xFF +/** @} */ +/*---------------------------------------------------------------------------*/ /** * \name Device string used on startup * @{ diff --git a/arch/platform/srf06-cc26xx/sensortag/cc1350/leds-arch.c b/arch/platform/srf06-cc26xx/sensortag/cc1350/leds-arch.c index f4214628e9790821b1d92eb5e7521d76757d8737..8da95520fd1da205ad0131666169808d87c6d808 100644 --- a/arch/platform/srf06-cc26xx/sensortag/cc1350/leds-arch.c +++ b/arch/platform/srf06-cc26xx/sensortag/cc1350/leds-arch.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright @@ -28,50 +29,13 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** - * \addtogroup sensortag-cc13xx-peripherals - * @{ - * - * \file - * Driver for the Sensortag-CC1350 LEDs - */ -/*---------------------------------------------------------------------------*/ #include "contiki.h" #include "dev/leds.h" +#include "dev/gpio-hal.h" -#include "ti-lib.h" -/*---------------------------------------------------------------------------*/ -static unsigned char c; -static int inited = 0; -/*---------------------------------------------------------------------------*/ -void -leds_arch_init(void) -{ - if(inited) { - return; - } - inited = 1; - - ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_LED_1); - - ti_lib_gpio_clear_multi_dio(BOARD_LED_ALL); -} +#include <stdbool.h> /*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - return c; -} -/*---------------------------------------------------------------------------*/ -void -leds_arch_set(unsigned char leds) -{ - c = leds; - ti_lib_gpio_clear_dio(BOARD_IOID_LED_1); - - if((leds & LEDS_RED) == LEDS_RED) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_1); - } -} +const leds_t leds_arch_leds[] = { + { .pin = BOARD_IOID_LED_1, .negative_logic = false }, +}; /*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/srf06-cc26xx/sensortag/cc2650/Makefile.cc2650 b/arch/platform/srf06-cc26xx/sensortag/cc2650/Makefile.cc2650 index 5b7cdadd9aa490e2d1f6c32415dfc2eab7a5729f..e91cabda4680d462ba69f6f4a15bb800cb9e4c7e 100644 --- a/arch/platform/srf06-cc26xx/sensortag/cc2650/Makefile.cc2650 +++ b/arch/platform/srf06-cc26xx/sensortag/cc2650/Makefile.cc2650 @@ -1,6 +1,3 @@ -### Add to the source list -BOARD_SOURCEFILES += leds-arch.c - ### Will allow the inclusion of the correct CPU makefile CPU_FAMILY = cc26xx diff --git a/arch/platform/srf06-cc26xx/sensortag/cc2650/board.h b/arch/platform/srf06-cc26xx/sensortag/cc2650/board.h index 0cf8288503e7edfec665df04dc0d96dbf4d081d3..7da0e945854ff4d5e067455babf28979cd44f273 100644 --- a/arch/platform/srf06-cc26xx/sensortag/cc2650/board.h +++ b/arch/platform/srf06-cc26xx/sensortag/cc2650/board.h @@ -58,27 +58,14 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -/* Some files include leds.h before us, so we need to get rid of defaults in - * leds.h before we provide correct definitions */ -#undef LEDS_GREEN -#undef LEDS_YELLOW -#undef LEDS_RED -#undef LEDS_CONF_ALL - -#define LEDS_RED 1 -#define LEDS_GREEN 2 -#define LEDS_YELLOW LEDS_GREEN -#define LEDS_ORANGE LEDS_RED - -#define LEDS_CONF_ALL 3 - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 2 +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -89,9 +76,6 @@ */ #define BOARD_IOID_LED_1 IOID_10 #define BOARD_IOID_LED_2 IOID_15 -#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) -#define BOARD_LED_2 (1 << BOARD_IOID_LED_2) -#define BOARD_LED_ALL (BOARD_LED_1 | BOARD_LED_2) /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -131,20 +115,6 @@ #define BOARD_KEY_RIGHT (1 << BOARD_IOID_KEY_RIGHT) /** @} */ /*---------------------------------------------------------------------------*/ -/** - * \brief SPI IOID mappings - * - * Those values are not meant to be modified by the user - * @{ - */ -#define BOARD_IOID_SPI_SCK IOID_17 -#define BOARD_IOID_SPI_MOSI IOID_19 -#define BOARD_IOID_SPI_MISO IOID_18 -#define BOARD_SPI_SCK (1 << BOARD_IOID_SPI_SCK) -#define BOARD_SPI_MOSI (1 << BOARD_IOID_SPI_MOSI) -#define BOARD_SPI_MISO (1 << BOARD_IOID_SPI_MISO) -/** @} */ -/*---------------------------------------------------------------------------*/ /** * \name Buzzer configuration * @{ @@ -167,9 +137,23 @@ * Those values are not meant to be modified by the user * @{ */ -#define BOARD_IOID_FLASH_CS IOID_14 -#define BOARD_FLASH_CS (1 << BOARD_IOID_FLASH_CS) -#define BOARD_IOID_SPI_CLK_FLASH IOID_17 +#define EXT_FLASH_SPI_CONTROLLER SPI_CONTROLLER_SPI0 + +#define BOARD_IOID_FLASH_SCK IOID_17 +#define BOARD_IOID_FLASH_MOSI IOID_19 +#define BOARD_IOID_FLASH_MISO IOID_18 +#define BOARD_IOID_FLASH_CS IOID_14 + +#define EXT_FLASH_SPI_PIN_SCK 17 +#define EXT_FLASH_SPI_PIN_MOSI 19 +#define EXT_FLASH_SPI_PIN_MISO 18 +#define EXT_FLASH_SPI_PIN_CS 14 + +#define EXT_FLASH_DEVICE_ID 0x14 +#define EXT_FLASH_MID 0xC2 + +#define EXT_FLASH_PROGRAM_PAGE_SIZE 256 +#define EXT_FLASH_ERASE_SECTOR_SIZE 4096 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -234,6 +218,17 @@ #define BOARD_IOID_AUDIO_CLK IOID_11 /** @} */ /*---------------------------------------------------------------------------*/ +/** + * \brief Board indices for the button HAL + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_BUTTON_HAL_INDEX_KEY_LEFT 0x00 +#define BOARD_BUTTON_HAL_INDEX_KEY_RIGHT 0x01 +#define BOARD_BUTTON_HAL_INDEX_REED_RELAY 0xFF +/** @} */ +/*---------------------------------------------------------------------------*/ /** * \name Device string used on startup * @{ diff --git a/arch/platform/srf06-cc26xx/sensortag/cc2650/leds-arch.c b/arch/platform/srf06-cc26xx/sensortag/cc2650/leds-arch.c index c369590634cab0f2c10c02723549fecbab6dcece..ac4abb7d5cd9774597a4c4e8ef617bdb3ec4ed58 100644 --- a/arch/platform/srf06-cc26xx/sensortag/cc2650/leds-arch.c +++ b/arch/platform/srf06-cc26xx/sensortag/cc2650/leds-arch.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright @@ -28,54 +29,14 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** - * \addtogroup sensortag-cc26xx-peripherals - * @{ - * - * \file - * Driver for the Sensortag-CC26XX LEDs - */ -/*---------------------------------------------------------------------------*/ #include "contiki.h" #include "dev/leds.h" +#include "dev/gpio-hal.h" -#include "ti-lib.h" -/*---------------------------------------------------------------------------*/ -static unsigned char c; -static int inited = 0; -/*---------------------------------------------------------------------------*/ -void -leds_arch_init(void) -{ - if(inited) { - return; - } - inited = 1; - - ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_LED_1); - ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_LED_2); - - ti_lib_gpio_clear_multi_dio(BOARD_LED_ALL); -} +#include <stdbool.h> /*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - return c; -} -/*---------------------------------------------------------------------------*/ -void -leds_arch_set(unsigned char leds) -{ - c = leds; - ti_lib_gpio_clear_multi_dio(BOARD_LED_ALL); - - if((leds & LEDS_RED) == LEDS_RED) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_1); - } - if((leds & LEDS_YELLOW) == LEDS_YELLOW) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_2); - } -} +const leds_t leds_arch_leds[] = { + { .pin = BOARD_IOID_LED_1, .negative_logic = false }, + { .pin = BOARD_IOID_LED_2, .negative_logic = false }, +}; /*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/srf06-cc26xx/sensortag/reed-relay.c b/arch/platform/srf06-cc26xx/sensortag/reed-relay.c deleted file mode 100644 index 736b2170a84d4b38666a7fa512792cd6cd01516e..0000000000000000000000000000000000000000 --- a/arch/platform/srf06-cc26xx/sensortag/reed-relay.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/*---------------------------------------------------------------------------*/ -/** - * \addtogroup sensortag-cc26xx-reed-relay - * @{ - * - * \file - * Driver for the Sensortag Reed Relay - */ -/*---------------------------------------------------------------------------*/ -#include "contiki.h" -#include "sys/clock.h" -#include "sys/timer.h" -#include "lib/sensors.h" -#include "sensortag/reed-relay.h" -#include "gpio-interrupt.h" -#include "sys/timer.h" - -#include "ti-lib.h" - -#include <stdint.h> -/*---------------------------------------------------------------------------*/ -static struct timer debouncetimer; -/*---------------------------------------------------------------------------*/ -#define REED_IO_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \ - IOC_IOPULL_DOWN | IOC_SLEW_DISABLE | \ - IOC_HYST_DISABLE | IOC_BOTH_EDGES | \ - IOC_INT_DISABLE | IOC_IOMODE_NORMAL | \ - IOC_NO_WAKE_UP | IOC_INPUT_ENABLE) -/*---------------------------------------------------------------------------*/ -/** - * \brief Handler for Sensortag-CC26XX reed interrupts - */ -static void -reed_interrupt_handler(uint8_t ioid) -{ - if(!timer_expired(&debouncetimer)) { - return; - } - - sensors_changed(&reed_relay_sensor); - timer_set(&debouncetimer, CLOCK_SECOND / 2); -} -/*---------------------------------------------------------------------------*/ -static int -value(int type) -{ - return (int)ti_lib_gpio_read_dio(BOARD_IOID_REED_RELAY); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Configuration function for the button sensor for all buttons. - * - * \param type SENSORS_HW_INIT: Initialise. SENSORS_ACTIVE: Enables/Disables - * depending on 'value' - * \param value 0: disable, non-zero: enable - * \return Always returns 1 - */ -static int -configure(int type, int value) -{ - switch(type) { - case SENSORS_HW_INIT: - ti_lib_ioc_int_disable(BOARD_IOID_REED_RELAY); - ti_lib_gpio_clear_event_dio(BOARD_IOID_REED_RELAY); - - /* Enable the GPIO clock when the CM3 is running */ - ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_GPIO); - - /* S/W control, input, pull-down */ - ti_lib_ioc_port_configure_set(BOARD_IOID_REED_RELAY, IOC_PORT_GPIO, - REED_IO_CFG); - - gpio_interrupt_register_handler(BOARD_IOID_REED_RELAY, - reed_interrupt_handler); - break; - case SENSORS_ACTIVE: - if(value) { - ti_lib_ioc_int_enable(BOARD_IOID_REED_RELAY); - } else { - ti_lib_ioc_int_disable(BOARD_IOID_REED_RELAY); - } - break; - default: - break; - } - return 1; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Status function for the reed - * \param type SENSORS_ACTIVE or SENSORS_READY - * \return 1 Interrupt enabled, 0: Disabled - */ -static int -status(int type) -{ - switch(type) { - case SENSORS_ACTIVE: - case SENSORS_READY: - return (ti_lib_ioc_port_configure_get(BOARD_IOID_REED_RELAY) - & IOC_INT_ENABLE) == IOC_INT_ENABLE; - break; - default: - break; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -SENSORS_SENSOR(reed_relay_sensor, "REED", value, configure, status); -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/srf06-cc26xx/sensortag/sensortag-sensors.c b/arch/platform/srf06-cc26xx/sensortag/sensortag-sensors.c index 26d08591d4fad3bfbbcfe5fd166d38b7e2cb83a8..065ef6112362f3e2ced6d2f2cf661d8b2e5f2a0b 100644 --- a/arch/platform/srf06-cc26xx/sensortag/sensortag-sensors.c +++ b/arch/platform/srf06-cc26xx/sensortag/sensortag-sensors.c @@ -37,19 +37,16 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "sensortag/button-sensor.h" #include "sensortag/bmp-280-sensor.h" #include "sensortag/tmp-007-sensor.h" #include "sensortag/opt-3001-sensor.h" #include "sensortag/hdc-1000-sensor.h" #include "sensortag/mpu-9250-sensor.h" -#include "sensortag/reed-relay.h" #include <string.h> /*---------------------------------------------------------------------------*/ /** \brief Exports a global symbol to be used by the sensor API */ -SENSORS(&button_left_sensor, &button_right_sensor, - &bmp_280_sensor, &tmp_007_sensor, &opt_3001_sensor, &hdc_1000_sensor, - &mpu_9250_sensor, &reed_relay_sensor); +SENSORS(&bmp_280_sensor, &tmp_007_sensor, &opt_3001_sensor, &hdc_1000_sensor, + &mpu_9250_sensor); /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/arch/platform/srf06-cc26xx/srf06/Makefile.srf06 b/arch/platform/srf06-cc26xx/srf06/Makefile.srf06 index 44d115ec8d80416f2a7f5b248beb2acb45200e62..dde7e967202fc9398abe4ff9356fd279aeb3f789 100644 --- a/arch/platform/srf06-cc26xx/srf06/Makefile.srf06 +++ b/arch/platform/srf06-cc26xx/srf06/Makefile.srf06 @@ -2,7 +2,7 @@ CFLAGS += -DBOARD_SMARTRF06EB=1 CONTIKI_TARGET_DIRS += srf06 -BOARD_SOURCEFILES += leds-arch.c srf06-sensors.c button-sensor.c board.c +BOARD_SOURCEFILES += srf06-sensors.c board-buttons.c board.c BOARD_SOURCEFILES += als-sensor.c ### Signal that we can be programmed with cc2538-bsl diff --git a/arch/platform/srf06-cc26xx/srf06/board-buttons.c b/arch/platform/srf06-cc26xx/srf06/board-buttons.c new file mode 100644 index 0000000000000000000000000000000000000000..c0db8daaaa22fcb7f8fd01fbc6b0cf8667cf4cec --- /dev/null +++ b/arch/platform/srf06-cc26xx/srf06/board-buttons.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup srf06-common-peripherals + * @{ + * + * \file + * Defines SmarfRF06 + CC13xxEM/CC26xxEM buttons for use with the button HAL + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/button-hal.h" + +#include "ti-lib.h" +/*---------------------------------------------------------------------------*/ +BUTTON_HAL_BUTTON(key_left, "Key Left", BOARD_IOID_KEY_LEFT, \ + GPIO_HAL_PIN_CFG_PULL_UP, BOARD_BUTTON_HAL_INDEX_KEY_LEFT, \ + true); +BUTTON_HAL_BUTTON(key_right, "Key Right", BOARD_IOID_KEY_RIGHT, \ + GPIO_HAL_PIN_CFG_PULL_UP, BOARD_BUTTON_HAL_INDEX_KEY_RIGHT, \ + true); +BUTTON_HAL_BUTTON(key_up, "Key Up", BOARD_IOID_KEY_UP, \ + GPIO_HAL_PIN_CFG_PULL_UP, BOARD_BUTTON_HAL_INDEX_KEY_UP, \ + true); +BUTTON_HAL_BUTTON(key_down, "Key Down", BOARD_IOID_KEY_DOWN, \ + GPIO_HAL_PIN_CFG_PULL_UP, BOARD_BUTTON_HAL_INDEX_KEY_DOWN, \ + true); +BUTTON_HAL_BUTTON(key_select, "Key Select", BOARD_IOID_KEY_SELECT, \ + GPIO_HAL_PIN_CFG_PULL_UP, \ + BOARD_BUTTON_HAL_INDEX_KEY_SELECT, true); +/*---------------------------------------------------------------------------*/ +BUTTON_HAL_BUTTONS(&key_left, &key_right, &key_up, &key_down, &key_select); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/arch/platform/srf06-cc26xx/srf06/button-sensor.c b/arch/platform/srf06-cc26xx/srf06/button-sensor.c deleted file mode 100644 index 23f668355e205eedec7bc0f8380b7405875efbb7..0000000000000000000000000000000000000000 --- a/arch/platform/srf06-cc26xx/srf06/button-sensor.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/*---------------------------------------------------------------------------*/ -/** - * \addtogroup srf06-common-peripherals - * @{ - * - * \file - * Driver for the SmartRF06EB buttons when a CC13xx/CC26xxEM is mounted on it - */ -/*---------------------------------------------------------------------------*/ -#include "contiki.h" -#include "lib/sensors.h" -#include "srf06/button-sensor.h" -#include "gpio-interrupt.h" -#include "sys/timer.h" -#include "lpm.h" - -#include "ti-lib.h" - -#include <stdint.h> -/*---------------------------------------------------------------------------*/ -#ifdef BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN -#define BUTTON_SENSOR_ENABLE_SHUTDOWN BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN -#else -#define BUTTON_SENSOR_ENABLE_SHUTDOWN 1 -#endif -/*---------------------------------------------------------------------------*/ -#define BUTTON_GPIO_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \ - IOC_IOPULL_UP | IOC_SLEW_DISABLE | \ - IOC_HYST_DISABLE | IOC_BOTH_EDGES | \ - IOC_INT_ENABLE | IOC_IOMODE_NORMAL | \ - IOC_NO_WAKE_UP | IOC_INPUT_ENABLE) -/*---------------------------------------------------------------------------*/ -#define DEBOUNCE_DURATION (CLOCK_SECOND >> 5) - -struct btn_timer { - struct timer debounce; - clock_time_t start; - clock_time_t duration; -}; - -static struct btn_timer sel_timer, left_timer, right_timer, up_timer, - down_timer; -/*---------------------------------------------------------------------------*/ -/** - * \brief Handler for SmartRF button presses - */ -static void -button_press_handler(uint8_t ioid) -{ - if(ioid == BOARD_IOID_KEY_SELECT) { - if(!timer_expired(&sel_timer.debounce)) { - return; - } - - timer_set(&sel_timer.debounce, DEBOUNCE_DURATION); - - /* - * Start press duration counter on press (falling), notify on release - * (rising) - */ - if(ti_lib_gpio_read_dio(BOARD_IOID_KEY_SELECT) == 0) { - sel_timer.start = clock_time(); - sel_timer.duration = 0; - } else { - sel_timer.duration = clock_time() - sel_timer.start; - sensors_changed(&button_select_sensor); - } - } - - if(ioid == BOARD_IOID_KEY_LEFT) { - if(!timer_expired(&left_timer.debounce)) { - return; - } - - timer_set(&left_timer.debounce, DEBOUNCE_DURATION); - - /* - * Start press duration counter on press (falling), notify on release - * (rising) - */ - if(ti_lib_gpio_read_dio(BOARD_IOID_KEY_LEFT) == 0) { - left_timer.start = clock_time(); - left_timer.duration = 0; - } else { - left_timer.duration = clock_time() - left_timer.start; - sensors_changed(&button_left_sensor); - } - } - - if(ioid == BOARD_IOID_KEY_RIGHT) { - if(BUTTON_SENSOR_ENABLE_SHUTDOWN == 0) { - if(!timer_expired(&right_timer.debounce)) { - return; - } - - timer_set(&right_timer.debounce, DEBOUNCE_DURATION); - - /* - * Start press duration counter on press (falling), notify on release - * (rising) - */ - if(ti_lib_gpio_read_dio(BOARD_IOID_KEY_RIGHT) == 0) { - right_timer.start = clock_time(); - right_timer.duration = 0; - } else { - right_timer.duration = clock_time() - right_timer.start; - sensors_changed(&button_right_sensor); - } - } else { - lpm_shutdown(BOARD_IOID_KEY_RIGHT, IOC_IOPULL_UP, IOC_WAKE_ON_LOW); - } - } - - if(ioid == BOARD_IOID_KEY_UP) { - if(!timer_expired(&up_timer.debounce)) { - return; - } - - timer_set(&up_timer.debounce, DEBOUNCE_DURATION); - - /* - * Start press duration counter on press (falling), notify on release - * (rising) - */ - if(ti_lib_gpio_read_dio(BOARD_IOID_KEY_UP) == 0) { - up_timer.start = clock_time(); - up_timer.duration = 0; - } else { - up_timer.duration = clock_time() - up_timer.start; - sensors_changed(&button_up_sensor); - } - } - - if(ioid == BOARD_IOID_KEY_DOWN) { - if(!timer_expired(&down_timer.debounce)) { - return; - } - - timer_set(&down_timer.debounce, DEBOUNCE_DURATION); - - /* - * Start press duration counter on press (falling), notify on release - * (rising) - */ - if(ti_lib_gpio_read_dio(BOARD_IOID_KEY_DOWN) == 0) { - down_timer.start = clock_time(); - down_timer.duration = 0; - } else { - down_timer.duration = clock_time() - down_timer.start; - sensors_changed(&button_down_sensor); - } - } -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Configuration function for the button sensor for all buttons. - * - * \param type This function does nothing unless type == SENSORS_ACTIVE - * \param c 0: disable the button, non-zero: enable - * \param key: One of BOARD_KEY_LEFT, BOARD_KEY_RIGHT etc - */ -static void -config_buttons(int type, int c, uint32_t key) -{ - switch(type) { - case SENSORS_HW_INIT: - ti_lib_gpio_clear_event_dio(key); - ti_lib_rom_ioc_pin_type_gpio_input(key); - ti_lib_rom_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG); - gpio_interrupt_register_handler(key, button_press_handler); - break; - case SENSORS_ACTIVE: - if(c) { - ti_lib_gpio_clear_event_dio(key); - ti_lib_rom_ioc_pin_type_gpio_input(key); - ti_lib_rom_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG); - ti_lib_rom_ioc_int_enable(key); - } else { - ti_lib_rom_ioc_int_disable(key); - } - break; - default: - break; - } -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Configuration function for the select button. - * - * Parameters are passed onto config_buttons, which does the actual - * configuration - * Parameters are ignored. They have been included because the prototype is - * dictated by the core sensor api. The return value is also required by - * the API but otherwise ignored. - * - * \param type passed to config_buttons as-is - * \param value passed to config_buttons as-is - * - * \return ignored - */ -static int -config_select(int type, int value) -{ - config_buttons(type, value, BOARD_IOID_KEY_SELECT); - - return 1; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Configuration function for the left button. - * - * Parameters are passed onto config_buttons, which does the actual - * configuration - * Parameters are ignored. They have been included because the prototype is - * dictated by the core sensor api. The return value is also required by - * the API but otherwise ignored. - * - * \param type passed to config_buttons as-is - * \param value passed to config_buttons as-is - * - * \return ignored - */ -static int -config_left(int type, int value) -{ - config_buttons(type, value, BOARD_IOID_KEY_LEFT); - - return 1; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Configuration function for the right button. - * - * Parameters are passed onto config_buttons, which does the actual - * configuration - * Parameters are ignored. They have been included because the prototype is - * dictated by the core sensor api. The return value is also required by - * the API but otherwise ignored. - * - * \param type passed to config_buttons as-is - * \param value passed to config_buttons as-is - * - * \return ignored - */ -static int -config_right(int type, int value) -{ - config_buttons(type, value, BOARD_IOID_KEY_RIGHT); - - return 1; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Configuration function for the up button. - * - * Parameters are passed onto config_buttons, which does the actual - * configuration - * Parameters are ignored. They have been included because the prototype is - * dictated by the core sensor api. The return value is also required by - * the API but otherwise ignored. - * - * \param type passed to config_buttons as-is - * \param value passed to config_buttons as-is - * - * \return ignored - */ -static int -config_up(int type, int value) -{ - config_buttons(type, value, BOARD_IOID_KEY_UP); - - return 1; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Configuration function for the down button. - * - * Parameters are passed onto config_buttons, which does the actual - * configuration - * Parameters are ignored. They have been included because the prototype is - * dictated by the core sensor api. The return value is also required by - * the API but otherwise ignored. - * - * \param type passed to config_buttons as-is - * \param value passed to config_buttons as-is - * - * \return ignored - */ -static int -config_down(int type, int value) -{ - config_buttons(type, value, BOARD_IOID_KEY_DOWN); - - return 1; -} -/*---------------------------------------------------------------------------*/ -static int -value_select(int type) -{ - if(type == BUTTON_SENSOR_VALUE_STATE) { - return ti_lib_gpio_read_dio(BOARD_IOID_KEY_SELECT) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; - } else if(type == BUTTON_SENSOR_VALUE_DURATION) { - return (int)sel_timer.duration; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -static int -value_left(int type) -{ - if(type == BUTTON_SENSOR_VALUE_STATE) { - return ti_lib_gpio_read_dio(BOARD_IOID_KEY_LEFT) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; - } else if(type == BUTTON_SENSOR_VALUE_DURATION) { - return (int)left_timer.duration; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -static int -value_right(int type) -{ - if(type == BUTTON_SENSOR_VALUE_STATE) { - return ti_lib_gpio_read_dio(BOARD_IOID_KEY_RIGHT) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; - } else if(type == BUTTON_SENSOR_VALUE_DURATION) { - return (int)right_timer.duration; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -static int -value_up(int type) -{ - if(type == BUTTON_SENSOR_VALUE_STATE) { - return ti_lib_gpio_read_dio(BOARD_IOID_KEY_UP) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; - } else if(type == BUTTON_SENSOR_VALUE_DURATION) { - return (int)up_timer.duration; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -static int -value_down(int type) -{ - if(type == BUTTON_SENSOR_VALUE_STATE) { - return ti_lib_gpio_read_dio(BOARD_IOID_KEY_DOWN) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; - } else if(type == BUTTON_SENSOR_VALUE_DURATION) { - return (int)down_timer.duration; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Status function for all buttons - * \param type SENSORS_ACTIVE or SENSORS_READY - * \param key_io_id BOARD_IOID_KEY_LEFT, BOARD_IOID_KEY_RIGHT etc - * \return 1 if the button's port interrupt is enabled (edge detect) - * - * This function will only be called by status_left, status_right and the - * called will pass the correct key_io_id - */ -static int -status(int type, uint32_t key_io_id) -{ - switch(type) { - case SENSORS_ACTIVE: - case SENSORS_READY: - if(ti_lib_ioc_port_configure_get(key_io_id) & IOC_INT_ENABLE) { - return 1; - } - break; - default: - break; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Status function for the select button. - * \param type SENSORS_ACTIVE or SENSORS_READY - * \return 1 if the button's port interrupt is enabled (edge detect) - * - * This function will call status. It will pass type verbatim and it will also - * pass the correct key_io_id - */ -static int -status_select(int type) -{ - return status(type, BOARD_IOID_KEY_SELECT); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Status function for the left button. - * \param type SENSORS_ACTIVE or SENSORS_READY - * \return 1 if the button's port interrupt is enabled (edge detect) - * - * This function will call status. It will pass type verbatim and it will also - * pass the correct key_io_id - */ -static int -status_left(int type) -{ - return status(type, BOARD_IOID_KEY_LEFT); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Status function for the right button. - * \param type SENSORS_ACTIVE or SENSORS_READY - * \return 1 if the button's port interrupt is enabled (edge detect) - * - * This function will call status. It will pass type verbatim and it will also - * pass the correct key_io_id - */ -static int -status_right(int type) -{ - return status(type, BOARD_IOID_KEY_RIGHT); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Status function for the up button. - * \param type SENSORS_ACTIVE or SENSORS_READY - * \return 1 if the button's port interrupt is enabled (edge detect) - * - * This function will call status. It will pass type verbatim and it will also - * pass the correct key_io_id - */ -static int -status_up(int type) -{ - return status(type, BOARD_IOID_KEY_UP); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Status function for the down button. - * \param type SENSORS_ACTIVE or SENSORS_READY - * \return 1 if the button's port interrupt is enabled (edge detect) - * - * This function will call status. It will pass type verbatim and it will also - * pass the correct key_io_id - */ -static int -status_down(int type) -{ - return status(type, BOARD_IOID_KEY_DOWN); -} -/*---------------------------------------------------------------------------*/ -SENSORS_SENSOR(button_select_sensor, BUTTON_SENSOR, value_select, - config_select, status_select); -SENSORS_SENSOR(button_left_sensor, BUTTON_SENSOR, value_left, config_left, - status_left); -SENSORS_SENSOR(button_right_sensor, BUTTON_SENSOR, value_right, config_right, - status_right); -SENSORS_SENSOR(button_up_sensor, BUTTON_SENSOR, value_up, config_up, status_up); -SENSORS_SENSOR(button_down_sensor, BUTTON_SENSOR, value_down, config_down, - status_down); -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/srf06-cc26xx/srf06/cc13xx/board.h b/arch/platform/srf06-cc26xx/srf06/cc13xx/board.h index 831c2ee331ffe4621dbd6159985bd993047ce90e..9fece91806d50a298da5124dcab5c9556d8ec74b 100644 --- a/arch/platform/srf06-cc26xx/srf06/cc13xx/board.h +++ b/arch/platform/srf06-cc26xx/srf06/cc13xx/board.h @@ -58,27 +58,16 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -/* Some files include leds.h before us, so we need to get rid of defaults in - * leds.h before we provide correct definitions */ -#undef LEDS_GREEN -#undef LEDS_YELLOW -#undef LEDS_RED -#undef LEDS_CONF_ALL - -#define LEDS_RED 1 /**< LED1 (Red) */ -#define LEDS_YELLOW 2 /**< LED2 (Yellow) */ -#define LEDS_GREEN 4 /**< LED3 (Green) */ -#define LEDS_ORANGE 8 /**< LED4 (Orange) */ - -#define LEDS_CONF_ALL 15 - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 4 +#define LEDS_CONF_RED 1 +#define LEDS_CONF_YELLOW 2 +#define LEDS_CONF_GREEN 4 +#define LEDS_CONF_ORANGE 8 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -91,12 +80,6 @@ #define BOARD_IOID_LED_2 IOID_27 #define BOARD_IOID_LED_3 IOID_7 #define BOARD_IOID_LED_4 IOID_6 -#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) -#define BOARD_LED_2 (1 << BOARD_IOID_LED_2) -#define BOARD_LED_3 (1 << BOARD_IOID_LED_3) -#define BOARD_LED_4 (1 << BOARD_IOID_LED_4) -#define BOARD_LED_ALL (BOARD_LED_1 | BOARD_LED_2 | BOARD_LED_3 | \ - BOARD_LED_4) /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -249,6 +232,19 @@ #endif /** @} */ /*---------------------------------------------------------------------------*/ +/** + * \brief Board indices for the button HAL + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_BUTTON_HAL_INDEX_KEY_LEFT 0x00 +#define BOARD_BUTTON_HAL_INDEX_KEY_RIGHT 0x01 +#define BOARD_BUTTON_HAL_INDEX_KEY_UP 0x02 +#define BOARD_BUTTON_HAL_INDEX_KEY_DOWN 0x03 +#define BOARD_BUTTON_HAL_INDEX_KEY_SELECT 0x04 +/** @} */ +/*---------------------------------------------------------------------------*/ /** * \name Device string used on startup * @{ diff --git a/arch/platform/srf06-cc26xx/srf06/cc26xx/board.h b/arch/platform/srf06-cc26xx/srf06/cc26xx/board.h index 35080aea94e0f7213f02b32b36c1afd202514751..b9171388a1462cacb2fcfe0515a1c556fb04273b 100644 --- a/arch/platform/srf06-cc26xx/srf06/cc26xx/board.h +++ b/arch/platform/srf06-cc26xx/srf06/cc26xx/board.h @@ -58,27 +58,16 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -/* Some files include leds.h before us, so we need to get rid of defaults in - * leds.h before we provide correct definitions */ -#undef LEDS_GREEN -#undef LEDS_YELLOW -#undef LEDS_RED -#undef LEDS_CONF_ALL - -#define LEDS_RED 1 /**< LED1 (Red) */ -#define LEDS_YELLOW 2 /**< LED2 (Yellow) */ -#define LEDS_GREEN 4 /**< LED3 (Green) */ -#define LEDS_ORANGE 8 /**< LED4 (Orange) */ - -#define LEDS_CONF_ALL 15 - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 4 +#define LEDS_CONF_RED 1 +#define LEDS_CONF_YELLOW 2 +#define LEDS_CONF_GREEN 4 +#define LEDS_CONF_ORANGE 8 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -91,12 +80,6 @@ #define BOARD_IOID_LED_2 IOID_27 #define BOARD_IOID_LED_3 IOID_7 #define BOARD_IOID_LED_4 IOID_6 -#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) -#define BOARD_LED_2 (1 << BOARD_IOID_LED_2) -#define BOARD_LED_3 (1 << BOARD_IOID_LED_3) -#define BOARD_LED_4 (1 << BOARD_IOID_LED_4) -#define BOARD_LED_ALL (BOARD_LED_1 | BOARD_LED_2 | BOARD_LED_3 | \ - BOARD_LED_4) /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -249,6 +232,19 @@ #endif /** @} */ /*---------------------------------------------------------------------------*/ +/** + * \brief Board indices for the button HAL + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_BUTTON_HAL_INDEX_KEY_LEFT 0x00 +#define BOARD_BUTTON_HAL_INDEX_KEY_RIGHT 0x01 +#define BOARD_BUTTON_HAL_INDEX_KEY_UP 0x02 +#define BOARD_BUTTON_HAL_INDEX_KEY_DOWN 0x03 +#define BOARD_BUTTON_HAL_INDEX_KEY_SELECT 0x04 +/** @} */ +/*---------------------------------------------------------------------------*/ /** * \name Device string used on startup * @{ diff --git a/arch/platform/srf06-cc26xx/srf06/leds-arch.c b/arch/platform/srf06-cc26xx/srf06/leds-arch.c index 2a162700587d06973c1440608b087bbc3004eb3d..f504f9cc2483416b21cf88aded13522d5675528a 100644 --- a/arch/platform/srf06-cc26xx/srf06/leds-arch.c +++ b/arch/platform/srf06-cc26xx/srf06/leds-arch.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright @@ -28,63 +29,16 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** - * \addtogroup srf06-common-peripherals - * @{ - * - * \file - * Driver for the SmartRF06EB LEDs when a CC13xx/CC26xx EM is mounted on it - */ -/*---------------------------------------------------------------------------*/ #include "contiki.h" #include "dev/leds.h" -#include "ti-lib.h" -/*---------------------------------------------------------------------------*/ -static unsigned char c; -static int inited = 0; -/*---------------------------------------------------------------------------*/ -void -leds_arch_init(void) -{ - if(inited) { - return; - } - inited = 1; - - ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_LED_1); - ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_LED_2); - ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_LED_3); - ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_LED_4); +#include "dev/gpio-hal.h" - ti_lib_gpio_clear_multi_dio(BOARD_LED_ALL); -} -/*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - return c; -} +#include <stdbool.h> /*---------------------------------------------------------------------------*/ -void -leds_arch_set(unsigned char leds) -{ - c = leds; - - /* Clear everything */ - ti_lib_gpio_clear_multi_dio(BOARD_LED_ALL); - - if((leds & LEDS_RED) == LEDS_RED) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_1); - } - if((leds & LEDS_YELLOW) == LEDS_YELLOW) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_2); - } - if((leds & LEDS_GREEN) == LEDS_GREEN) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_3); - } - if((leds & LEDS_ORANGE) == LEDS_ORANGE) { - ti_lib_gpio_set_dio(BOARD_IOID_LED_4); - } -} +const leds_t leds_arch_leds[] = { + { .pin = BOARD_IOID_LED_1, .negative_logic = false }, + { .pin = BOARD_IOID_LED_2, .negative_logic = false }, + { .pin = BOARD_IOID_LED_3, .negative_logic = false }, + { .pin = BOARD_IOID_LED_4, .negative_logic = false }, +}; /*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/srf06-cc26xx/srf06/srf06-sensors.c b/arch/platform/srf06-cc26xx/srf06/srf06-sensors.c index 5f65a0cb215b601adeac64f95ce6750254a038ea..642d2b103b6913ab7e93699bff6a091fdb600989 100644 --- a/arch/platform/srf06-cc26xx/srf06/srf06-sensors.c +++ b/arch/platform/srf06-cc26xx/srf06/srf06-sensors.c @@ -38,13 +38,11 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "srf06/button-sensor.h" #include "srf06/als-sensor.h" #include <string.h> /*---------------------------------------------------------------------------*/ /** \brief Exports a global symbol to be used by the sensor API */ -SENSORS(&button_select_sensor, &button_left_sensor, &button_right_sensor, - &button_up_sensor, &button_down_sensor, &als_sensor); +SENSORS(&als_sensor); /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/arch/platform/zoul/Makefile.zoul b/arch/platform/zoul/Makefile.zoul index 9e25275a437ae46b60d48a23bcc4e4698ccdda96..586a74ae27abdfc3c1e5be8a7ac615cec100f795 100644 --- a/arch/platform/zoul/Makefile.zoul +++ b/arch/platform/zoul/Makefile.zoul @@ -31,22 +31,18 @@ PLATFORM_ROOT_DIR = $(CONTIKI)/arch/platform/$(TARGET) -include $(PLATFORM_ROOT_DIR)/$(BOARD)/Makefile.$(BOARD) ### Include -CONTIKI_TARGET_SOURCEFILES += platform.c +CONTIKI_TARGET_SOURCEFILES += platform.c leds-arch.c CONTIKI_TARGET_SOURCEFILES += leds.c cc1200-zoul-arch.c -CONTIKI_TARGET_SOURCEFILES += adc-zoul.c button-sensor.c zoul-sensors.c +CONTIKI_TARGET_SOURCEFILES += adc-zoul.c board-buttons.c zoul-sensors.c CONTIKI_TARGET_SOURCEFILES += $(BOARD_SOURCEFILES) CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) -CLEAN += *.zoul - ### Define the CPU directory CONTIKI_CPU=$(CONTIKI)/arch/cpu/cc2538 include $(CONTIKI_CPU)/Makefile.cc2538 -MODULES += os/net os/net/mac os/net/mac/framer \ - arch/dev/cc1200 \ - os/storage/cfs +MODULES += arch/dev/cc1200 arch/dev/rgb-led os/storage/cfs BSL = $(CONTIKI)/tools/cc2538-bsl/cc2538-bsl.py diff --git a/arch/platform/zoul/contiki-conf.h b/arch/platform/zoul/contiki-conf.h index 42f6661e1bf9cb522512b9879b1122f680cadb60..098c37404fe28708944152380fad6739ae9e2a30 100644 --- a/arch/platform/zoul/contiki-conf.h +++ b/arch/platform/zoul/contiki-conf.h @@ -29,7 +29,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /** - * \addtogroup platform + * \addtogroup zoul-core * @{ * * \defgroup zoul-platforms Zolertia Zoul platforms @@ -47,57 +47,14 @@ #include <stdint.h> #include <string.h> +#include <inttypes.h> /*---------------------------------------------------------------------------*/ /* Include Project Specific conf */ #ifdef PROJECT_CONF_PATH #include PROJECT_CONF_PATH #endif /* PROJECT_CONF_PATH */ /*---------------------------------------------------------------------------*/ -/** - * \name Compiler configuration and platform-specific type definitions - * - * Those values are not meant to be modified by the user - * @{ - */ -#define CLOCK_CONF_SECOND 128 - -/* Compiler configurations */ -#define CCIF -#define CLIF - -/* Platform typedefs */ -typedef uint32_t clock_time_t; -typedef uint32_t uip_stats_t; - -/* - * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define - * RTIMER_CLOCK_DIFF to override this - */ -typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_DIFF(a, b) ((int32_t)((a) - (b))) -/** @} */ -/*---------------------------------------------------------------------------*/ -/* 352us from calling transmit() until the SFD byte has been sent */ -#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(352)) -/* 192us as in datasheet but ACKs are not always received, so adjusted to 250us */ -#define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(250)) -#define RADIO_DELAY_BEFORE_DETECT 0 -#ifndef TSCH_CONF_BASE_DRIFT_PPM -/* The drift compared to "true" 10ms slots. - * Enable adaptive sync to enable compensation for this. - * Slot length 10000 usec - * 328 ticks - * Tick duration 30.517578125 usec - * Real slot duration 10009.765625 usec - * Target - real duration = -9.765625 usec - * TSCH_CONF_BASE_DRIFT_PPM -977 - */ -#define TSCH_CONF_BASE_DRIFT_PPM -977 -#endif - -#if MAC_CONF_WITH_TSCH -#define TSCH_CONF_HW_FRAME_FILTERING 0 -#endif /* MAC_CONF_WITH_TSCH */ +#include "cc2538-def.h" /*---------------------------------------------------------------------------*/ /** * \name Serial Boot Loader Backdoor configuration @@ -127,174 +84,10 @@ typedef uint32_t rtimer_clock_t; #endif /** @} */ /*---------------------------------------------------------------------------*/ -/** - * \name CFS configuration - * - * @{ - */ -#ifndef COFFEE_CONF_SIZE -#define COFFEE_CONF_SIZE (4 * COFFEE_SECTOR_SIZE) -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name Watchdog Timer configuration - * - * @{ - */ -#ifndef WATCHDOG_CONF_ENABLE -#define WATCHDOG_CONF_ENABLE 1 /**< Enable the watchdog timer */ -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name USB 'core' configuration - * - * Those values are not meant to be modified by the user, except where stated - * otherwise - * @{ - */ -#define CTRL_EP_SIZE 8 -#define USB_EP1_SIZE 32 -#define USB_EP2_SIZE 64 -#define USB_EP3_SIZE 64 -#define USB_ARCH_WRITE_NOTIFY 0 - -#ifndef USB_ARCH_CONF_DMA -#define USB_ARCH_CONF_DMA 1 /**< Change to Enable/Disable USB DMA */ - -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name uDMA Configuration and channel allocations - * - * @{ - */ -#define USB_ARCH_CONF_RX_DMA_CHAN 0 /**< USB -> RAM DMA channel */ -#define USB_ARCH_CONF_TX_DMA_CHAN 1 /**< RAM -> USB DMA channel */ -#define CC2538_RF_CONF_TX_DMA_CHAN 2 /**< RF -> RAM DMA channel */ -#define CC2538_RF_CONF_RX_DMA_CHAN 3 /**< RAM -> RF DMA channel */ -#define UDMA_CONF_MAX_CHANNEL CC2538_RF_CONF_RX_DMA_CHAN -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name Character I/O Configuration - * - * @{ - */ -#ifndef UART_CONF_ENABLE -#define UART_CONF_ENABLE 1 /**< Enable/Disable UART I/O */ -#endif - -#ifndef UART0_CONF_BAUD_RATE -#define UART0_CONF_BAUD_RATE 115200 /**< Default UART0 baud rate */ -#endif - -#ifndef UART1_CONF_BAUD_RATE -#define UART1_CONF_BAUD_RATE 115200 /**< Default UART1 baud rate */ -#endif - -#ifndef SLIP_ARCH_CONF_USB -#define SLIP_ARCH_CONF_USB 0 /**< SLIP over UART by default */ -#endif - -#ifndef DBG_CONF_USB -#define DBG_CONF_USB 0 /**< All debugging over UART by default */ -#endif - -#ifndef SERIAL_LINE_CONF_UART -#define SERIAL_LINE_CONF_UART 0 /**< UART to use with serial line */ -#endif - -#if !SLIP_ARCH_CONF_USB -#ifndef SLIP_ARCH_CONF_UART -#define SLIP_ARCH_CONF_UART 0 /**< UART to use with SLIP */ -#endif -#endif - -#if !DBG_CONF_USB -#ifndef DBG_CONF_UART -#define DBG_CONF_UART 0 /**< UART to use for debugging */ -#endif -#endif - -#ifndef UART1_CONF_UART -#define UART1_CONF_UART 0 /**< UART to use for examples relying on - the uart1_* API */ -#endif - -#ifndef SLIP_ARCH_CONF_ENABLED -/* - * Determine whether we need SLIP - * This will keep working while UIP_FALLBACK_INTERFACE and CMD_CONF_OUTPUT - * keep using SLIP - */ -#if defined(UIP_FALLBACK_INTERFACE) || defined(CMD_CONF_OUTPUT) -#define SLIP_ARCH_CONF_ENABLED 1 -#endif -#endif - -/** - * \brief Define this as 1 to build a headless node. - * - * The UART will not be initialised its clock will be gated, offering some - * energy savings. The USB will not be initialised either - */ -#ifndef CC2538_CONF_QUIET -#define CC2538_CONF_QUIET 0 -#endif - -/* CC2538_CONF_QUIET is hard and overrides all other related defines */ -#if CC2538_CONF_QUIET -#undef USB_SERIAL_CONF_ENABLE -#define USB_SERIAL_CONF_ENABLE 0 - -#undef UART_CONF_ENABLE -#define UART_CONF_ENABLE 0 -#endif /* CC2538_CONF_QUIET */ - -/** - * \brief Enable the USB core only if we need it - */ -#ifndef USB_SERIAL_CONF_ENABLE -#define USB_SERIAL_CONF_ENABLE \ - ((SLIP_ARCH_CONF_USB && SLIP_ARCH_CONF_ENABLED) || \ - (MAC_CONF_WITH_TSCH && (SLIP_ARCH_CONF_ENABLED || BUILD_WITH_SHELL)) || \ - DBG_CONF_USB) -#endif - -/* - * If debugging and SLIP use the same peripheral, this will be 1. Don't modify - * this - */ -#if SLIP_ARCH_CONF_ENABLED -#define DBG_CONF_SLIP_MUX (SLIP_ARCH_CONF_USB == DBG_CONF_USB && \ - (SLIP_ARCH_CONF_USB || \ - SLIP_ARCH_CONF_UART == DBG_CONF_UART)) -#endif - -/* - * Automatic detection of whether a specific UART is in use - */ -#define UART_IN_USE_BY_SERIAL_LINE(u) (SERIAL_LINE_CONF_UART == (u)) -#define UART_IN_USE_BY_SLIP(u) (SLIP_ARCH_CONF_ENABLED && \ - !SLIP_ARCH_CONF_USB && \ - SLIP_ARCH_CONF_UART == (u)) -#define UART_IN_USE_BY_DBG(u) (!DBG_CONF_USB && DBG_CONF_UART == (u)) -#define UART_IN_USE_BY_UART1(u) (UART1_CONF_UART == (u)) - -#define UART_IN_USE(u) ( \ - UART_CONF_ENABLE && \ - (UART_IN_USE_BY_SERIAL_LINE(u) || \ - UART_IN_USE_BY_SLIP(u) || \ - UART_IN_USE_BY_DBG(u) || \ - UART_IN_USE_BY_UART1(u)) \ -) -/** @} */ -/*---------------------------------------------------------------------------*/ /* board.h assumes that basic configuration is done */ #include "board.h" + +#define PLATFORM_SUPPORTS_BUTTON_HAL PLATFORM_HAS_BUTTON /*---------------------------------------------------------------------------*/ /** * \name Radio Configuration @@ -363,86 +156,6 @@ typedef uint32_t rtimer_clock_t; #endif /** @} */ /*---------------------------------------------------------------------------*/ -/** - * \name IEEE address configuration - * - * Used to generate our link-layer & IPv6 address - * @{ - */ -/** - * \brief Location of the IEEE address - * 0 => Read from InfoPage, - * 1 => Use a hardcoded address, configured by IEEE_ADDR_CONF_ADDRESS - */ -#ifndef IEEE_ADDR_CONF_HARDCODED -#define IEEE_ADDR_CONF_HARDCODED 0 -#endif - -/** - * \brief The hardcoded IEEE address to be used when IEEE_ADDR_CONF_HARDCODED - * is defined as 1 - */ -#ifndef IEEE_ADDR_CONF_ADDRESS -#define IEEE_ADDR_CONF_ADDRESS { 0x00, 0x12, 0x4B, 0x00, 0x89, 0xAB, 0xCD, 0xEF } -#endif - -/** - * \brief Location of the IEEE address in the InfoPage when - * IEEE_ADDR_CONF_HARDCODED is defined as 0 - * 0 => Use the primary address location - * 1 => Use the secondary address location - */ -#ifndef IEEE_ADDR_CONF_USE_SECONDARY_LOCATION -#define IEEE_ADDR_CONF_USE_SECONDARY_LOCATION 0 -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name RF configuration - * - * @{ - */ -/* RF Config */ - -#ifdef RF_CHANNEL -#define CC2538_RF_CONF_CHANNEL RF_CHANNEL -#endif - -#ifndef CC2538_RF_CONF_CHANNEL -#define CC2538_RF_CONF_CHANNEL 26 -#endif /* CC2538_RF_CONF_CHANNEL */ - -#ifndef CC2538_RF_CONF_AUTOACK -#define CC2538_RF_CONF_AUTOACK 1 /**< RF H/W generates ACKs */ -#endif /* CC2538_CONF_AUTOACK */ - -#ifndef CC2538_RF_CONF_TX_USE_DMA -#define CC2538_RF_CONF_TX_USE_DMA 1 /**< RF TX over DMA */ -#endif - -#ifndef CC2538_RF_CONF_RX_USE_DMA -#define CC2538_RF_CONF_RX_USE_DMA 1 /**< RF RX over DMA */ -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name Security - * - * @{ - */ -#ifndef CRYPTO_CONF_INIT -#define CRYPTO_CONF_INIT 1 /**< Whether to init cryptoprocessor */ -#endif - -#ifndef AES_128_CONF -#define AES_128_CONF cc2538_aes_128_driver /**< AES-128 driver */ -#endif - -#ifndef CCM_STAR_CONF -#define CCM_STAR_CONF cc2538_ccm_star_driver /**< AES-CCM* driver */ -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ /** * \name RTC * @@ -464,7 +177,9 @@ typedef uint32_t rtimer_clock_t; #endif /** @} */ /*---------------------------------------------------------------------------*/ - +/* Include CPU-related configuration */ +#include "cc2538-conf.h" +/*---------------------------------------------------------------------------*/ #endif /* CONTIKI_CONF_H_ */ - +/*---------------------------------------------------------------------------*/ /** @} */ diff --git a/arch/platform/zoul/dev/ac-dimmer.c b/arch/platform/zoul/dev/ac-dimmer.c index 5c27c2ffc66051e84a97aaba3cefdf9cc76e5b0c..e5bb9b1f4be49f2b28edbb6364548d993a8fd2a0 100644 --- a/arch/platform/zoul/dev/ac-dimmer.c +++ b/arch/platform/zoul/dev/ac-dimmer.c @@ -40,6 +40,7 @@ #include "contiki.h" #include "ac-dimmer.h" #include "dev/gpio.h" +#include "dev/gpio-hal.h" #include "lib/sensors.h" #include "dev/ioc.h" /*---------------------------------------------------------------------------*/ @@ -76,13 +77,17 @@ PROCESS_THREAD(ac_dimmer_int_process, ev, data) } /*---------------------------------------------------------------------------*/ static void -dimmer_zero_cross_int_handler(uint8_t port, uint8_t pin) +dimmer_zero_cross_int_handler(gpio_hal_pin_mask_t pin_mask) { - if((port == DIMMER_SYNC_PORT) && (pin == DIMMER_SYNC_PIN)) { - process_poll(&ac_dimmer_int_process); - } + process_poll(&ac_dimmer_int_process); } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t dimmer_handler = { + .next = NULL, + .handler = dimmer_zero_cross_int_handler, + .pin_mask = gpio_hal_pin_to_mask(DIMMER_SYNC_PIN) << (DIMMER_SYNC_PORT << 3), +}; +/*---------------------------------------------------------------------------*/ static int status(int type) { @@ -128,8 +133,7 @@ configure(int type, int value) GPIO_DETECT_EDGE(DIMMER_SYNC_PORT_BASE, DIMMER_SYNC_PIN_MASK); GPIO_TRIGGER_SINGLE_EDGE(DIMMER_SYNC_PORT_BASE, DIMMER_SYNC_PIN_MASK); GPIO_DETECT_RISING(DIMMER_SYNC_PORT_BASE, DIMMER_SYNC_PIN_MASK); - gpio_register_callback(dimmer_zero_cross_int_handler, DIMMER_SYNC_PORT, - DIMMER_SYNC_PIN); + gpio_hal_register_handler(&dimmer_handler); /* Spin process until an interrupt is received */ process_start(&ac_dimmer_int_process, NULL); diff --git a/arch/platform/srf06-cc26xx/sensortag/reed-relay.h b/arch/platform/zoul/dev/board-buttons.c similarity index 76% rename from arch/platform/srf06-cc26xx/sensortag/reed-relay.h rename to arch/platform/zoul/dev/board-buttons.c index 0ed6dd8190fad1ed72ebe516ad4791c11fe90600..93532caa417c601d25f4f5d892433725a7b626ca 100644 --- a/arch/platform/srf06-cc26xx/sensortag/reed-relay.h +++ b/arch/platform/zoul/dev/board-buttons.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright @@ -29,29 +30,30 @@ */ /*---------------------------------------------------------------------------*/ /** - * \addtogroup sensortag-cc26xx-peripherals + * \addtogroup zoul * @{ * - * \defgroup sensortag-cc26xx-reed-relay SensorTag 2.0 Reed Relay - * - * The reed relay acts like a button without a button. To trigger the reed, - * approach a magnet to the sensortag and a sensors_changed event will be - * generated, in a fashion similar to as if a button had been pressed + * \defgroup zoul-buttons Zoul user button * + * Generic module controlling the user button on the Zoul * @{ * * \file - * Header file for the Sensortag Reed Relay + * Defines the Zoul user button for use with the button HAL */ /*---------------------------------------------------------------------------*/ -#ifndef REED_RELAY_H -#define REED_RELAY_H +#include "contiki.h" +#include "dev/button-hal.h" +/*---------------------------------------------------------------------------*/ +#if PLATFORM_HAS_BUTTON /*---------------------------------------------------------------------------*/ -#include "lib/sensors.h" +BUTTON_HAL_BUTTON(button_user, "User button", \ + GPIO_PORT_PIN_TO_GPIO_HAL_PIN(BUTTON_USER_PORT, BUTTON_USER_PIN), \ + GPIO_HAL_PIN_CFG_PULL_UP, BUTTON_HAL_ID_USER_BUTTON, true); /*---------------------------------------------------------------------------*/ -extern const struct sensors_sensor reed_relay_sensor; +BUTTON_HAL_BUTTONS(&button_user); /*---------------------------------------------------------------------------*/ -#endif /* REED_RELAY_H */ +#endif /*---------------------------------------------------------------------------*/ /** * @} diff --git a/arch/platform/zoul/dev/button-sensor.c b/arch/platform/zoul/dev/button-sensor.c deleted file mode 100644 index 80c7b75cbc4d9b17341f065335f799e817a24031..0000000000000000000000000000000000000000 --- a/arch/platform/zoul/dev/button-sensor.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ - * Copyright (c) 2015, Zolertia - http://www.zolertia.com - * Copyright (c) 2015, University of Bristol - http://www.bristol.ac.uk - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/*---------------------------------------------------------------------------*/ -/** - * \addtogroup zoul-button-sensor - * @{ - * - * \file - * Driver for the Zoul user button - */ -/*---------------------------------------------------------------------------*/ -#include "contiki.h" -#include "dev/nvic.h" -#include "dev/ioc.h" -#include "dev/gpio.h" -#include "dev/button-sensor.h" -#include "sys/timer.h" -#include "sys/ctimer.h" -#include "sys/process.h" - -#include <stdint.h> -#include <string.h> -/*---------------------------------------------------------------------------*/ -#define BUTTON_USER_PORT_BASE GPIO_PORT_TO_BASE(BUTTON_USER_PORT) -#define BUTTON_USER_PIN_MASK GPIO_PIN_MASK(BUTTON_USER_PIN) -/*---------------------------------------------------------------------------*/ -#define DEBOUNCE_DURATION (CLOCK_SECOND >> 4) - -static struct timer debouncetimer; -/*---------------------------------------------------------------------------*/ -static clock_time_t press_duration = 0; -static struct ctimer press_counter; -static uint8_t press_event_counter; - -process_event_t button_press_duration_exceeded; -/*---------------------------------------------------------------------------*/ -static void -duration_exceeded_callback(void *data) -{ - press_event_counter++; - process_post(PROCESS_BROADCAST, button_press_duration_exceeded, - &press_event_counter); - ctimer_set(&press_counter, press_duration, duration_exceeded_callback, - NULL); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Retrieves the value of the button pin - * \param type Returns the pin level or the counter of press duration events. - * type == BUTTON_SENSOR_VALUE_TYPE_LEVEL or - * type == BUTTON_SENSOR_VALUE_TYPE_PRESS_DURATION - * respectively - */ -static int -value(int type) -{ - switch(type) { - case BUTTON_SENSOR_VALUE_TYPE_LEVEL: - return GPIO_READ_PIN(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); - case BUTTON_SENSOR_VALUE_TYPE_PRESS_DURATION: - return press_event_counter; - } - - return 0; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Callback registered with the GPIO module. Gets fired with a button - * port/pin generates an interrupt - * \param port The port number that generated the interrupt - * \param pin The pin number that generated the interrupt. This is the pin - * absolute number (i.e. 0, 1, ..., 7), not a mask - */ -static void -btn_callback(uint8_t port, uint8_t pin) -{ - if(!timer_expired(&debouncetimer)) { - return; - } - - timer_set(&debouncetimer, DEBOUNCE_DURATION); - - if(press_duration) { - press_event_counter = 0; - if(value(BUTTON_SENSOR_VALUE_TYPE_LEVEL) == BUTTON_SENSOR_PRESSED_LEVEL) { - ctimer_set(&press_counter, press_duration, duration_exceeded_callback, - NULL); - } else { - ctimer_stop(&press_counter); - } - } - - sensors_changed(&button_sensor); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Init function for the User button. - * \param type SENSORS_ACTIVE: Activate / Deactivate the sensor (value == 1 - * or 0 respectively) - * - * \param value Depends on the value of the type argument - * \return Depends on the value of the type argument - */ -static int -config_user(int type, int value) -{ - switch(type) { - case SENSORS_HW_INIT: - button_press_duration_exceeded = process_alloc_event(); - - /* Software controlled */ - GPIO_SOFTWARE_CONTROL(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); - - /* Set pin to input */ - GPIO_SET_INPUT(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); - - /* Enable edge detection */ - GPIO_DETECT_EDGE(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); - - /* Both Edges */ - GPIO_TRIGGER_BOTH_EDGES(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); - - ioc_set_over(BUTTON_USER_PORT, BUTTON_USER_PIN, IOC_OVERRIDE_PUE); - - gpio_register_callback(btn_callback, BUTTON_USER_PORT, BUTTON_USER_PIN); - break; - case SENSORS_ACTIVE: - if(value) { - GPIO_ENABLE_INTERRUPT(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); - NVIC_EnableIRQ(BUTTON_USER_VECTOR); - } else { - GPIO_DISABLE_INTERRUPT(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); - NVIC_DisableIRQ(BUTTON_USER_VECTOR); - } - return value; - case BUTTON_SENSOR_CONFIG_TYPE_INTERVAL: - press_duration = (clock_time_t)value; - break; - default: - break; - } - - return 1; -} -/*---------------------------------------------------------------------------*/ -SENSORS_SENSOR(button_sensor, BUTTON_SENSOR, value, config_user, NULL); -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/zoul/dev/button-sensor.h b/arch/platform/zoul/dev/button-sensor.h deleted file mode 100644 index 12e333c4a0ac6602f6873ddfb1ca9864d8d5f4e4..0000000000000000000000000000000000000000 --- a/arch/platform/zoul/dev/button-sensor.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ - * Copyright (c) 2015, Zolertia - http://www.zolertia.com - * Copyright (c) 2015, University of Bristol - http://www.bristol.ac.uk - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/*---------------------------------------------------------------------------*/ -/** - * \addtogroup zoul-sensors - * @{ - * - * \defgroup zoul-button-sensor Zoul User Button Driver - * - * Driver for the Zoul user button - * - * The user button (on Zoul-based platforms like the RE-Mote and the Firefly) - * will generate a sensors_changed event on press as well as on release. - * - * Unlike many other platforms, the user button has the ability to - * generate events when the user keeps the button pressed. The user can - * configure the button driver with a timer interval in clock ticks. When the - * button is kept pressed, the driver will then generate a broadcast event - * each time the interval passes. For example the driver can be configured to - * generate an event every second while the button is kept pressed. This - * functionality can be enabled through the configure() function, by passing - * BUTTON_SENSOR_CONFIG_TYPE_INTERVAL as the type argument. - * @{ - * - * \file - * Header file for the Zoul User Button Driver - */ -/*---------------------------------------------------------------------------*/ -#ifndef BUTTON_SENSOR_H_ -#define BUTTON_SENSOR_H_ -/*---------------------------------------------------------------------------*/ -#include "lib/sensors.h" -/*---------------------------------------------------------------------------*/ -#define BUTTON_SENSOR "Button" - -extern const struct sensors_sensor button_sensor; -/*---------------------------------------------------------------------------*/ -extern process_event_t button_press_duration_exceeded; -/*---------------------------------------------------------------------------*/ -#define BUTTON_SENSOR_CONFIG_TYPE_INTERVAL 0x0100 - -#define BUTTON_SENSOR_VALUE_TYPE_LEVEL 0 -#define BUTTON_SENSOR_VALUE_TYPE_PRESS_DURATION 1 - -#define BUTTON_SENSOR_PRESSED_LEVEL 0 -#define BUTTON_SENSOR_RELEASED_LEVEL 8 -/*---------------------------------------------------------------------------*/ -#endif /* BUTTON_SENSOR_H_ */ -/*---------------------------------------------------------------------------*/ -/** - * @} - * @} - */ diff --git a/arch/platform/zoul/dev/cc1200-zoul-arch.c b/arch/platform/zoul/dev/cc1200-zoul-arch.c index 92e686a4ed4a97ee140d922e7a35c7f4b98c0815..8c9d8cdd7e793277fc0162f8ba208866b1217a3a 100644 --- a/arch/platform/zoul/dev/cc1200-zoul-arch.c +++ b/arch/platform/zoul/dev/cc1200-zoul-arch.c @@ -46,12 +46,13 @@ #include "contiki-net.h" #include "dev/leds.h" #include "reg.h" -#include "spi-arch.h" +#include "dev/spi-arch-legacy.h" #include "dev/ioc.h" #include "dev/sys-ctrl.h" -#include "dev/spi.h" +#include "dev/spi-legacy.h" #include "dev/ssi.h" #include "dev/gpio.h" +#include "dev/gpio-hal.h" #include <stdio.h> /*---------------------------------------------------------------------------*/ #define CC1200_SPI_CLK_PORT_BASE GPIO_PORT_TO_BASE(SPI0_CLK_PORT) @@ -92,7 +93,7 @@ extern int cc1200_rx_interrupt(void); /*---------------------------------------------------------------------------*/ void -cc1200_int_handler(uint8_t port, uint8_t pin) +cc1200_int_handler(gpio_hal_pin_mask_t pin_mask) { /* To keep the gpio_register_callback happy */ cc1200_rx_interrupt(); @@ -166,6 +167,14 @@ cc1200_arch_spi_rw(uint8_t *inbuf, const uint8_t *write_buf, uint16_t len) return 0; } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t interrupt_handler = { + .next = NULL, + .handler = cc1200_int_handler, + .pin_mask = + (gpio_hal_pin_to_mask(CC1200_GDO0_PIN) << (CC1200_GDO0_PORT << 3)) | + (gpio_hal_pin_to_mask(CC1200_GDO2_PIN) << (CC1200_GDO2_PORT << 3)) +}; +/*---------------------------------------------------------------------------*/ void cc1200_arch_gpio0_setup_irq(int rising) { @@ -184,8 +193,7 @@ cc1200_arch_gpio0_setup_irq(int rising) GPIO_ENABLE_INTERRUPT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK); ioc_set_over(CC1200_GDO0_PORT, CC1200_GDO0_PIN, IOC_OVERRIDE_PUE); NVIC_EnableIRQ(CC1200_GPIOx_VECTOR); - gpio_register_callback(cc1200_int_handler, CC1200_GDO0_PORT, - CC1200_GDO0_PIN); + gpio_hal_register_handler(&interrupt_handler); } /*---------------------------------------------------------------------------*/ void @@ -206,8 +214,7 @@ cc1200_arch_gpio2_setup_irq(int rising) GPIO_ENABLE_INTERRUPT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK); ioc_set_over(CC1200_GDO2_PORT, CC1200_GDO2_PIN, IOC_OVERRIDE_PUE); NVIC_EnableIRQ(CC1200_GPIOx_VECTOR); - gpio_register_callback(cc1200_int_handler, CC1200_GDO2_PORT, - CC1200_GDO2_PIN); + gpio_hal_register_handler(&interrupt_handler); } /*---------------------------------------------------------------------------*/ void diff --git a/arch/platform/zoul/dev/grove-gyro.c b/arch/platform/zoul/dev/grove-gyro.c index ce316a2072a3ff6a547c35ff87ac11c035f8b37c..1ef9d60367716d43b3279416ec15f000ddf22235 100644 --- a/arch/platform/zoul/dev/grove-gyro.c +++ b/arch/platform/zoul/dev/grove-gyro.c @@ -44,6 +44,7 @@ #include "contiki.h" #include "dev/i2c.h" #include "dev/grove-gyro.h" +#include "dev/gpio-hal.h" #include "lib/sensors.h" #include "dev/watchdog.h" /*---------------------------------------------------------------------------*/ @@ -458,11 +459,17 @@ PROCESS_THREAD(grove_gyro_int_process, ev, data) } /*---------------------------------------------------------------------------*/ static void -grove_gyro_interrupt_handler(uint8_t port, uint8_t pin) +grove_gyro_interrupt_handler(gpio_hal_pin_mask_t pin_mask) { process_poll(&grove_gyro_int_process); } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t gyro_handler = { + .next = NULL, + .handler = grove_gyro_interrupt_handler, + .pin_mask = gpio_hal_pin_to_mask(I2C_INT_PIN) << (I2C_INT_PORT << 3), +}; +/*---------------------------------------------------------------------------*/ static int value(int type) { @@ -593,8 +600,7 @@ configure(int type, int value) GPIO_DETECT_EDGE(GROVE_GYRO_INT_PORT_BASE, GROVE_GYRO_INT_PIN_MASK); GPIO_TRIGGER_SINGLE_EDGE(GROVE_GYRO_INT_PORT_BASE, GROVE_GYRO_INT_PIN_MASK); GPIO_DETECT_FALLING(GROVE_GYRO_INT_PORT_BASE, GROVE_GYRO_INT_PIN_MASK); - gpio_register_callback(grove_gyro_interrupt_handler, I2C_INT_PORT, - I2C_INT_PIN); + gpio_hal_register_handler(&gyro_handler); /* Spin process until an interrupt is received */ process_start(&grove_gyro_int_process, NULL); diff --git a/arch/platform/zoul/dev/leds-arch.c b/arch/platform/zoul/dev/leds-arch.c index f09ed645c60a8d6b5aad6909ca62515ab580c2d2..ecb02b2f6a8bd85afeab9346d69da9bc9fababec 100644 --- a/arch/platform/zoul/dev/leds-arch.c +++ b/arch/platform/zoul/dev/leds-arch.c @@ -1,17 +1,16 @@ /* - * Copyright (c) 2015, Zolertia - http://www.zolertia.com - * Copyright (c) 2015, University of Bristol - http://www.bristol.ac.uk + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. @@ -29,45 +28,25 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * \addtogroup zoul - * @{ - * - * \defgroup zoul-leds Zoul LED driver - * - * LED driver implementation for the Zoul-based platforms - * @{ - * - * \file - * LED driver implementation for the Zoul-based platforms - */ +/*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "reg.h" #include "dev/leds.h" -#include "dev/gpio.h" -/*---------------------------------------------------------------------------*/ -#define LEDS_GPIO_PIN_MASK LEDS_ALL -/*---------------------------------------------------------------------------*/ -void -leds_arch_init(void) -{ - GPIO_SET_OUTPUT(GPIO_D_BASE, LEDS_GPIO_PIN_MASK); -} -/*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - return GPIO_READ_PIN(GPIO_D_BASE, LEDS_GPIO_PIN_MASK); -} +#include "dev/gpio-hal.h" + +#include <stdbool.h> /*---------------------------------------------------------------------------*/ -void -leds_arch_set(unsigned char leds) -{ - GPIO_WRITE_PIN(GPIO_D_BASE, LEDS_GPIO_PIN_MASK, leds); -} +const leds_t leds_arch_leds[] = { + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L1_PORT, LEDS_ARCH_L1_PIN), + .negative_logic = false + }, + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L2_PORT, LEDS_ARCH_L2_PIN), + .negative_logic = false + }, + { + .pin = GPIO_PORT_PIN_TO_GPIO_HAL_PIN(LEDS_ARCH_L3_PORT, LEDS_ARCH_L3_PIN), + .negative_logic = false + }, +}; /*---------------------------------------------------------------------------*/ - -/** - * @} - * @} - */ diff --git a/arch/platform/zoul/dev/mmc-arch.c b/arch/platform/zoul/dev/mmc-arch.c index b2aff5a467b3e6556c3d1440473a0eada1959ebc..f1eca8d322cc8a045279a16559a99abd0f02468d 100644 --- a/arch/platform/zoul/dev/mmc-arch.c +++ b/arch/platform/zoul/dev/mmc-arch.c @@ -39,10 +39,10 @@ #include <stddef.h> #include <stdbool.h> #include <stdint.h> -#include "spi-arch.h" +#include "dev/spi-arch-legacy.h" #include "dev/ioc.h" #include "dev/gpio.h" -#include "dev/spi.h" +#include "dev/spi-legacy.h" #include "mmc-arch.h" #define USD_SEL_PORT_BASE GPIO_PORT_TO_BASE(USD_SEL_PORT) diff --git a/arch/platform/zoul/dev/motion-sensor.c b/arch/platform/zoul/dev/motion-sensor.c index ce31c3c46ef9186e05fbedcb460a7f059a54a4dc..a44462d69d5623b574d12080f39e36e3d2054aba 100644 --- a/arch/platform/zoul/dev/motion-sensor.c +++ b/arch/platform/zoul/dev/motion-sensor.c @@ -47,6 +47,7 @@ #include "lib/sensors.h" #include "dev/sys-ctrl.h" #include "dev/gpio.h" +#include "dev/gpio-hal.h" #include "dev/ioc.h" /*---------------------------------------------------------------------------*/ #define DEBUG 0 @@ -76,11 +77,17 @@ PROCESS_THREAD(motion_int_process, ev, data) } /*---------------------------------------------------------------------------*/ static void -motion_interrupt_handler(uint8_t port, uint8_t pin) +motion_interrupt_handler(gpio_hal_pin_mask_t pin_mask) { process_poll(&motion_int_process); } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t motion_handler = { + .next = NULL, + .handler = motion_interrupt_handler, + .pin_mask = gpio_hal_pin_to_mask(MOTION_SENSOR_PIN) << (MOTION_SENSOR_PORT << 3), +}; +/*---------------------------------------------------------------------------*/ static int status(int type) { @@ -113,8 +120,7 @@ configure(int type, int value) GPIO_DETECT_RISING(MOTION_SENSOR_PORT_BASE, MOTION_SENSOR_PIN_MASK); GPIO_TRIGGER_SINGLE_EDGE(MOTION_SENSOR_PORT_BASE, MOTION_SENSOR_PIN_MASK); ioc_set_over(MOTION_SENSOR_PORT, MOTION_SENSOR_PIN, IOC_OVERRIDE_DIS); - gpio_register_callback(motion_interrupt_handler, MOTION_SENSOR_PORT, - MOTION_SENSOR_PIN); + gpio_hal_register_handler(&motion_handler); process_start(&motion_int_process, NULL); diff --git a/arch/platform/zoul/dev/rtcc.c b/arch/platform/zoul/dev/rtcc.c index b5cb116c3ed1dbf61ce4639042808eced1b0c199..d03413d5bda0164a1ae976973717c617ebf4e496 100644 --- a/arch/platform/zoul/dev/rtcc.c +++ b/arch/platform/zoul/dev/rtcc.c @@ -735,7 +735,7 @@ rtcc_print(uint8_t value) } /*---------------------------------------------------------------------------*/ static void -rtcc_interrupt_handler(uint8_t port, uint8_t pin) +rtcc_interrupt_handler(gpio_hal_pin_mask_t pin_mask) { process_poll(&rtcc_int_process); } @@ -912,6 +912,12 @@ rtcc_set_calibration(uint8_t mode, int32_t adjust) return AB08_SUCCESS; } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t rtcc_handler = { + .next = NULL, + .handler = rtcc_interrupt_handler, + .pin_mask = gpio_hal_pin_to_mask(RTC_INT1_PIN) << (RTC_INT1_PORT << 3), +}; +/*---------------------------------------------------------------------------*/ int8_t rtcc_init(void) { @@ -937,7 +943,7 @@ rtcc_init(void) GPIO_DETECT_EDGE(RTC_INT1_PORT_BASE, RTC_INT1_PIN_MASK); GPIO_TRIGGER_SINGLE_EDGE(RTC_INT1_PORT_BASE, RTC_INT1_PIN_MASK); GPIO_DETECT_FALLING(RTC_INT1_PORT_BASE, RTC_INT1_PIN_MASK); - gpio_register_callback(rtcc_interrupt_handler, RTC_INT1_PORT, RTC_INT1_PIN); + gpio_hal_register_handler(&rtcc_handler); /* Spin process until an interrupt is received */ process_start(&rtcc_int_process, NULL); diff --git a/arch/platform/zoul/dev/tsl256x.c b/arch/platform/zoul/dev/tsl256x.c index 3f68705474075039773a062f47575500a54e362a..ffcf2e218c1b61e5dbb663e19015a7c23c7f3f3b 100644 --- a/arch/platform/zoul/dev/tsl256x.c +++ b/arch/platform/zoul/dev/tsl256x.c @@ -43,6 +43,7 @@ #include "contiki.h" #include "dev/i2c.h" #include "dev/gpio.h" +#include "dev/gpio-hal.h" #include "dev/zoul-sensors.h" #include "lib/sensors.h" #include "tsl256x.h" @@ -255,7 +256,7 @@ PROCESS_THREAD(tsl256x_int_process, ev, data) } /*---------------------------------------------------------------------------*/ static void -tsl256x_interrupt_handler(uint8_t port, uint8_t pin) +tsl256x_interrupt_handler(gpio_hal_pin_mask_t pin_mask) { /* There's no alert/interruption flag to check, clear the interruption by * writting to the CLEAR bit in the COMMAND register @@ -263,6 +264,12 @@ tsl256x_interrupt_handler(uint8_t port, uint8_t pin) process_poll(&tsl256x_int_process); } /*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t tsl256x_handler = { + .next = NULL, + .handler = tsl256x_interrupt_handler, + .pin_mask = gpio_hal_pin_to_mask(I2C_INT_PIN) << (I2C_INT_PORT << 3), +}; +/*---------------------------------------------------------------------------*/ static int configure(int type, int value) { @@ -440,7 +447,7 @@ configure(int type, int value) GPIO_DETECT_EDGE(TSL256X_INT_PORT_BASE, TSL256X_INT_PIN_MASK); GPIO_TRIGGER_SINGLE_EDGE(TSL256X_INT_PORT_BASE, TSL256X_INT_PIN_MASK); GPIO_DETECT_FALLING(TSL256X_INT_PORT_BASE, TSL256X_INT_PIN_MASK); - gpio_register_callback(tsl256x_interrupt_handler, I2C_INT_PORT, I2C_INT_PIN); + gpio_hal_register_handler(&tsl256x_handler); /* Spin process until an interrupt is received */ process_start(&tsl256x_int_process, NULL); diff --git a/arch/platform/zoul/dev/weather-meter.c b/arch/platform/zoul/dev/weather-meter.c index 357c37d4b4c6ba5f968cabb59e210106c1626cfe..cc78f9654eac79fa1e275ba0f9952338f5d74699 100644 --- a/arch/platform/zoul/dev/weather-meter.c +++ b/arch/platform/zoul/dev/weather-meter.c @@ -51,6 +51,7 @@ #include "lib/sensors.h" #include "dev/sys-ctrl.h" #include "dev/gpio.h" +#include "dev/gpio-hal.h" #include "dev/ioc.h" #include "sys/timer.h" #include "sys/ctimer.h" @@ -292,8 +293,22 @@ PROCESS_THREAD(weather_meter_int_process, ev, data) PROCESS_END(); } /*---------------------------------------------------------------------------*/ +static void weather_meter_interrupt_handler(gpio_hal_pin_mask_t pin_mask); +/*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t rain_handler = { + .next = NULL, + .handler = weather_meter_interrupt_handler, + .pin_mask = gpio_hal_pin_to_mask(RAIN_GAUGE_SENSOR_PIN) << (RAIN_GAUGE_SENSOR_PORT << 3), +}; +/*---------------------------------------------------------------------------*/ +static gpio_hal_event_handler_t anemometer_handler = { + .next = NULL, + .handler = weather_meter_interrupt_handler, + .pin_mask = gpio_hal_pin_to_mask(ANEMOMETER_SENSOR_PIN) << (ANEMOMETER_SENSOR_PORT << 3), +}; +/*---------------------------------------------------------------------------*/ static void -weather_meter_interrupt_handler(uint8_t port, uint8_t pin) +weather_meter_interrupt_handler(gpio_hal_pin_mask_t pin_mask) { uint32_t aux; @@ -308,10 +323,10 @@ weather_meter_interrupt_handler(uint8_t port, uint8_t pin) * value */ - if((port == ANEMOMETER_SENSOR_PORT) && (pin == ANEMOMETER_SENSOR_PIN)) { + if(pin_mask == rain_handler.pin_mask) { weather_sensors.anemometer.ticks++; process_post(&weather_meter_int_process, anemometer_int_event, NULL); - } else if((port == RAIN_GAUGE_SENSOR_PORT) && (pin == RAIN_GAUGE_SENSOR_PIN)) { + } else if(pin_mask == anemometer_handler.pin_mask) { weather_sensors.rain_gauge.ticks++; aux = weather_sensors.rain_gauge.ticks * WEATHER_METER_AUX_RAIN_MM; aux /= 1000; @@ -427,8 +442,7 @@ configure(int type, int value) GPIO_TRIGGER_SINGLE_EDGE(ANEMOMETER_SENSOR_PORT_BASE, ANEMOMETER_SENSOR_PIN_MASK); ioc_set_over(ANEMOMETER_SENSOR_PORT, ANEMOMETER_SENSOR_PIN, IOC_OVERRIDE_DIS); - gpio_register_callback(weather_meter_interrupt_handler, ANEMOMETER_SENSOR_PORT, - ANEMOMETER_SENSOR_PIN); + gpio_hal_register_handler(&anemometer_handler); /* Configure rain gauge interruption */ GPIO_SOFTWARE_CONTROL(RAIN_GAUGE_SENSOR_PORT_BASE, RAIN_GAUGE_SENSOR_PIN_MASK); @@ -437,8 +451,7 @@ configure(int type, int value) GPIO_TRIGGER_SINGLE_EDGE(RAIN_GAUGE_SENSOR_PORT_BASE, RAIN_GAUGE_SENSOR_PIN_MASK); ioc_set_over(RAIN_GAUGE_SENSOR_PORT, RAIN_GAUGE_SENSOR_PIN, IOC_OVERRIDE_DIS); - gpio_register_callback(weather_meter_interrupt_handler, RAIN_GAUGE_SENSOR_PORT, - RAIN_GAUGE_SENSOR_PIN); + gpio_hal_register_handler(&rain_handler); process_start(&weather_meter_int_process, NULL); diff --git a/arch/platform/zoul/dev/zoul-sensors.c b/arch/platform/zoul/dev/zoul-sensors.c index da755fc790cbae5e651ba407823baf709f42ce44..8015a183e53aa32b7755d3df31b41c14df36b30b 100644 --- a/arch/platform/zoul/dev/zoul-sensors.c +++ b/arch/platform/zoul/dev/zoul-sensors.c @@ -47,12 +47,7 @@ #include <string.h> /*---------------------------------------------------------------------------*/ /** \brief Exports global symbols for the sensor API */ -SENSORS(&vdd3_sensor, -#if PLATFORM_HAS_BUTTON - &button_sensor, -#endif - &cc2538_temp_sensor -); +SENSORS(&vdd3_sensor, &cc2538_temp_sensor); /*---------------------------------------------------------------------------*/ /** * @} diff --git a/arch/platform/zoul/dev/zoul-sensors.h b/arch/platform/zoul/dev/zoul-sensors.h index 5682c972c848dc915dbc0ea3696f67ce19ac7fc9..92635810ab6a8781e19a221f72be483a2dace750 100644 --- a/arch/platform/zoul/dev/zoul-sensors.h +++ b/arch/platform/zoul/dev/zoul-sensors.h @@ -48,7 +48,6 @@ /*---------------------------------------------------------------------------*/ #include "lib/sensors.h" #include "dev/cc2538-sensors.h" -#include "dev/button-sensor.h" /*---------------------------------------------------------------------------*/ /** * \name Zoul sensor constants diff --git a/arch/platform/zoul/doxygen-group.txt b/arch/platform/zoul/doxygen-group.txt new file mode 100644 index 0000000000000000000000000000000000000000..9090c239010d4fae0c2906a2beec1637791030bf --- /dev/null +++ b/arch/platform/zoul/doxygen-group.txt @@ -0,0 +1,4 @@ +/** + * \defgroup zoul-core Zolertia Zoul-based platforms + * \ingroup cc2538-platforms + */ diff --git a/arch/platform/zoul/firefly-reva/Makefile.firefly-reva b/arch/platform/zoul/firefly-reva/Makefile.firefly-reva index 50cb71997b41b005b828bbf6b77d98d19f541eed..afecf9fa57dbb6257810ed30537e85854bd958d5 100644 --- a/arch/platform/zoul/firefly-reva/Makefile.firefly-reva +++ b/arch/platform/zoul/firefly-reva/Makefile.firefly-reva @@ -1,2 +1,2 @@ MOTELIST_ZOLERTIA = firefly -BOARD_SOURCEFILES += board.c leds-arch.c +BOARD_SOURCEFILES += board.c diff --git a/arch/platform/zoul/firefly-reva/board.h b/arch/platform/zoul/firefly-reva/board.h index fb72796c00c2ff6f491166bca3873d9a017c4eef..784f9e902c88ac7a00071159c01fdb7c891fa082 100644 --- a/arch/platform/zoul/firefly-reva/board.h +++ b/arch/platform/zoul/firefly-reva/board.h @@ -98,28 +98,18 @@ * @{ */ /*---------------------------------------------------------------------------*/ -/* Some files include leds.h before us, so we need to get rid of defaults in - * leds.h before we provide correct definitions */ -#undef LEDS_GREEN -#undef LEDS_YELLOW -#undef LEDS_BLUE -#undef LEDS_RED -#undef LEDS_CONF_ALL +#define LEDS_ARCH_L1_PORT GPIO_D_NUM +#define LEDS_ARCH_L1_PIN 5 +#define LEDS_ARCH_L2_PORT GPIO_D_NUM +#define LEDS_ARCH_L2_PIN 4 +#define LEDS_ARCH_L3_PORT GPIO_D_NUM +#define LEDS_ARCH_L3_PIN 3 -/* In leds.h the LEDS_BLUE is defined by LED_YELLOW definition */ -#define LEDS_GREEN (1 << 4) /**< LED1 (Green) -> PD4 */ -#define LEDS_BLUE (1 << 3) /**< LED2 (Blue) -> PD3 */ -#define LEDS_RED (1 << 5) /**< LED3 (Red) -> PD5 */ +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_BLUE 4 -#define LEDS_CONF_ALL (LEDS_GREEN | LEDS_BLUE | LEDS_RED) - -#define LEDS_LIGHT_BLUE (LEDS_GREEN | LEDS_BLUE) /**< Green + Blue (24) */ -#define LEDS_YELLOW (LEDS_GREEN | LEDS_RED) /**< Green + Red (48) */ -#define LEDS_PURPLE (LEDS_BLUE | LEDS_RED) /**< Blue + Red (40) */ -#define LEDS_WHITE LEDS_ALL /**< Green + Blue + Red (56) */ - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 3 /** @} */ /*---------------------------------------------------------------------------*/ /** \name USB configuration diff --git a/arch/platform/zoul/firefly/Makefile.firefly b/arch/platform/zoul/firefly/Makefile.firefly index 50cb71997b41b005b828bbf6b77d98d19f541eed..afecf9fa57dbb6257810ed30537e85854bd958d5 100644 --- a/arch/platform/zoul/firefly/Makefile.firefly +++ b/arch/platform/zoul/firefly/Makefile.firefly @@ -1,2 +1,2 @@ MOTELIST_ZOLERTIA = firefly -BOARD_SOURCEFILES += board.c leds-arch.c +BOARD_SOURCEFILES += board.c diff --git a/arch/platform/zoul/firefly/board.h b/arch/platform/zoul/firefly/board.h index 0d90e4369a72959bf71329da0b116147f827cfc8..0367ea8df47bf84b46856160d9c3daf99d5b2551 100644 --- a/arch/platform/zoul/firefly/board.h +++ b/arch/platform/zoul/firefly/board.h @@ -98,28 +98,18 @@ * @{ */ /*---------------------------------------------------------------------------*/ -/* Some files include leds.h before us, so we need to get rid of defaults in - * leds.h before we provide correct definitions */ -#undef LEDS_GREEN -#undef LEDS_YELLOW -#undef LEDS_BLUE -#undef LEDS_RED -#undef LEDS_CONF_ALL +#define LEDS_ARCH_L1_PORT GPIO_D_NUM +#define LEDS_ARCH_L1_PIN 5 +#define LEDS_ARCH_L2_PORT GPIO_D_NUM +#define LEDS_ARCH_L2_PIN 4 +#define LEDS_ARCH_L3_PORT GPIO_D_NUM +#define LEDS_ARCH_L3_PIN 3 -/* In leds.h the LEDS_BLUE is defined by LED_YELLOW definition */ -#define LEDS_GREEN (1 << 4) /**< LED1 (Green) -> PD4 */ -#define LEDS_BLUE (1 << 3) /**< LED2 (Blue) -> PD3 */ -#define LEDS_RED (1 << 5) /**< LED3 (Red) -> PD5 */ +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_BLUE 4 -#define LEDS_CONF_ALL (LEDS_GREEN | LEDS_BLUE | LEDS_RED) - -#define LEDS_LIGHT_BLUE (LEDS_GREEN | LEDS_BLUE) /**< Green + Blue (24) */ -#define LEDS_YELLOW (LEDS_GREEN | LEDS_RED) /**< Green + Red (48) */ -#define LEDS_PURPLE (LEDS_BLUE | LEDS_RED) /**< Blue + Red (40) */ -#define LEDS_WHITE LEDS_ALL /**< Green + Blue + Red (56) */ - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 3 /** @} */ /*---------------------------------------------------------------------------*/ /** \name USB configuration diff --git a/arch/platform/zoul/orion/Makefile.orion b/arch/platform/zoul/orion/Makefile.orion index 7c5804d39f79bd014ed2579e372e6653784c6e6b..ebc1bdad4237a5abdf45aea9ecf45886be071a82 100644 --- a/arch/platform/zoul/orion/Makefile.orion +++ b/arch/platform/zoul/orion/Makefile.orion @@ -1,6 +1,7 @@ MOTELIST_ZOLERTIA = orion MODULES += arch/dev/enc28j60 CC2538_ENC28J60_ARCH ?= gpio -WITH_IP64 ?= 1 +ifeq ($(WITH_IP64),1) CFLAGS += -DUIP_FALLBACK_INTERFACE=ip64_uip_fallback_interface +endif BOARD_SOURCEFILES += board.c enc28j60-arch-$(CC2538_ENC28J60_ARCH).c leds-arch.c diff --git a/arch/platform/zoul/orion/board.h b/arch/platform/zoul/orion/board.h index f0e7ba452b70ac655d9e78465bb427271033042b..ee80cc7091efac26bdc40454617862c75d929ca8 100644 --- a/arch/platform/zoul/orion/board.h +++ b/arch/platform/zoul/orion/board.h @@ -67,28 +67,18 @@ * @{ */ /*---------------------------------------------------------------------------*/ -/* Some files include leds.h before us, so we need to get rid of defaults in - * leds.h before we provide correct definitions */ -#undef LEDS_GREEN -#undef LEDS_YELLOW -#undef LEDS_BLUE -#undef LEDS_RED -#undef LEDS_CONF_ALL +#define LEDS_ARCH_L1_PORT GPIO_D_NUM +#define LEDS_ARCH_L1_PIN 5 +#define LEDS_ARCH_L2_PORT GPIO_D_NUM +#define LEDS_ARCH_L2_PIN 4 +#define LEDS_ARCH_L3_PORT GPIO_D_NUM +#define LEDS_ARCH_L3_PIN 3 -/* In leds.h the LEDS_BLUE is defined by LED_YELLOW definition */ -#define LEDS_GREEN (1 << 4) /**< LED1 (Green) -> PD4 */ -#define LEDS_BLUE (1 << 3) /**< LED2 (Blue) -> PD3 */ -#define LEDS_RED (1 << 5) /**< LED3 (Red) -> PD5 */ +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_BLUE 4 -#define LEDS_CONF_ALL (LEDS_GREEN | LEDS_BLUE | LEDS_RED) - -#define LEDS_LIGHT_BLUE (LEDS_GREEN | LEDS_BLUE) /**< Green + Blue (24) */ -#define LEDS_YELLOW (LEDS_GREEN | LEDS_RED) /**< Green + Red (48) */ -#define LEDS_PURPLE (LEDS_BLUE | LEDS_RED) /**< Blue + Red (40) */ -#define LEDS_WHITE LEDS_ALL /**< Green + Blue + Red (56) */ - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 3 /** @} */ /*---------------------------------------------------------------------------*/ /** \name USB configuration diff --git a/arch/platform/zoul/orion/enc28j60-arch-spi.c b/arch/platform/zoul/orion/enc28j60-arch-spi.c index 59e6e4260bbd9cc9f4b3e087f0caccc6e7b9c5f6..bc9c9dadd74a373617bdeef5b82ea399bdb47961 100644 --- a/arch/platform/zoul/orion/enc28j60-arch-spi.c +++ b/arch/platform/zoul/orion/enc28j60-arch-spi.c @@ -43,8 +43,8 @@ * eth-gw SPI arch specifics */ /*---------------------------------------------------------------------------*/ -#include "spi-arch.h" -#include "spi.h" +#include "dev/spi-arch-legacy.h" +#include "dev/spi-legacy.h" #include "dev/gpio.h" /*---------------------------------------------------------------------------*/ #define RESET_PORT GPIO_PORT_TO_BASE(ETH_RESET_PORT) diff --git a/arch/platform/zoul/platform.c b/arch/platform/zoul/platform.c index da106a69787faf161bfeeff51603f7cdc19ef2b3..8cce149ee6bc101d063986fa0cbfb84cd7d5a1b8 100644 --- a/arch/platform/zoul/platform.c +++ b/arch/platform/zoul/platform.c @@ -30,7 +30,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /** - * \addtogroup platform + * \addtogroup zoul-core * @{ * * \defgroup zoul Zolertia Zoul core module @@ -54,8 +54,10 @@ #include "dev/udma.h" #include "dev/crypto.h" #include "dev/rtcc.h" +#include "dev/button-hal.h" #include "usb/usb-serial.h" #include "lib/random.h" +#include "lib/sensors.h" #include "net/netstack.h" #include "net/mac/framer/frame802154.h" #include "net/linkaddr.h" @@ -69,6 +71,7 @@ #include <stdint.h> #include <string.h> #include <stdio.h> +#include <stdlib.h> /*---------------------------------------------------------------------------*/ /* Log configuration */ #include "sys/log.h" @@ -81,7 +84,7 @@ void board_init(void); /*---------------------------------------------------------------------------*/ static void -fade(unsigned char l) +fade(leds_mask_t l) { volatile int i; int k, j; @@ -90,11 +93,11 @@ fade(unsigned char l) leds_on(l); for(i = 0; i < j; ++i) { - asm("nop"); + __asm("nop"); } leds_off(l); for(i = 0; i < 400 - j; ++i) { - asm("nop"); + __asm("nop"); } } } @@ -124,7 +127,7 @@ rtc_init(void) */ /* Get the system date in the following format: wd dd mm yy hh mm ss */ - PRINTF("Setting RTC from system date: %s\n", DATE); + LOG_INFO("Setting RTC from system date: %s\n", DATE); /* Configure the RTC with the current values */ td.weekdays = (uint8_t)strtol(DATE, &next, 10); @@ -149,7 +152,7 @@ rtc_init(void) /* Set the time and date */ if(rtcc_set_time_date(&td) == AB08_ERROR) { - PRINTF("Failed to set time and date\n"); + LOG_ERR("Failed to set time and date\n"); } #endif #endif @@ -166,9 +169,6 @@ set_rf_params(void) short_addr = ext_addr[7]; short_addr |= ext_addr[6] << 8; - /* Populate linkaddr_node_addr. Maintain endianness */ - memcpy(&linkaddr_node_addr, &ext_addr[8 - LINKADDR_SIZE], LINKADDR_SIZE); - NETSTACK_RADIO.set_value(RADIO_PARAM_PAN_ID, IEEE802154_PANID); NETSTACK_RADIO.set_value(RADIO_PARAM_16BIT_ADDR, short_addr); NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, CC2538_RF_CHANNEL); @@ -220,7 +220,12 @@ platform_init_stage_two() crypto_disable(); #endif - set_rf_params(); + /* Populate linkaddr_node_addr */ + ieee_addr_cpy_to(linkaddr_node_addr.u8, LINKADDR_SIZE); + +#if PLATFORM_HAS_BUTTON + button_hal_init(); +#endif INTERRUPTS_ENABLE(); @@ -232,6 +237,8 @@ platform_init_stage_three() { LOG_INFO("%s\n", BOARD_STRING); + set_rf_params(); + board_init(); rtc_init(); @@ -240,10 +247,6 @@ platform_init_stage_three() process_start(&sensors_process, NULL); -#if PLATFORM_HAS_BUTTON - SENSORS_ACTIVATE(button_sensor); -#endif - fade(LEDS_GREEN); } /*---------------------------------------------------------------------------*/ diff --git a/arch/platform/zoul/remote-reva/Makefile.remote-reva b/arch/platform/zoul/remote-reva/Makefile.remote-reva index 6b4a80e75f9232a3dc06cff579da66119f128a58..fcccdf0f477fe5fe92a875a6c0b7f1db2dd2ac51 100644 --- a/arch/platform/zoul/remote-reva/Makefile.remote-reva +++ b/arch/platform/zoul/remote-reva/Makefile.remote-reva @@ -1,4 +1,4 @@ MOTELIST_ZOLERTIA = remote -BOARD_SOURCEFILES += board.c antenna-sw.c mmc-arch.c rtcc.c power-mgmt.c leds-arch.c +BOARD_SOURCEFILES += board.c antenna-sw.c mmc-arch.c rtcc.c power-mgmt.c MODULES += os/lib/fs/fat os/lib/fs/fat/option arch/platform/zoul/fs/fat arch/dev/disk/mmc diff --git a/arch/platform/zoul/remote-reva/board.h b/arch/platform/zoul/remote-reva/board.h index efb516c31622f7f926eead4617e1cbede8524341..23722badd40ef833e1529cdb5bf8087f7b2f3df8 100644 --- a/arch/platform/zoul/remote-reva/board.h +++ b/arch/platform/zoul/remote-reva/board.h @@ -102,28 +102,18 @@ * @{ */ /*---------------------------------------------------------------------------*/ -/* Some files include leds.h before us, so we need to get rid of defaults in - * leds.h before we provide correct definitions */ -#undef LEDS_GREEN -#undef LEDS_YELLOW -#undef LEDS_BLUE -#undef LEDS_RED -#undef LEDS_CONF_ALL +#define LEDS_ARCH_L1_PORT GPIO_D_NUM +#define LEDS_ARCH_L1_PIN 5 +#define LEDS_ARCH_L2_PORT GPIO_D_NUM +#define LEDS_ARCH_L2_PIN 4 +#define LEDS_ARCH_L3_PORT GPIO_D_NUM +#define LEDS_ARCH_L3_PIN 3 -/* In leds.h the LEDS_BLUE is defined by LED_YELLOW definition */ -#define LEDS_GREEN (1 << 4) /**< LED1 (Green) -> PD4 */ -#define LEDS_BLUE (1 << 3) /**< LED2 (Blue) -> PD3 */ -#define LEDS_RED (1 << 5) /**< LED3 (Red) -> PD5 */ +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_BLUE 4 -#define LEDS_CONF_ALL (LEDS_GREEN | LEDS_BLUE | LEDS_RED) - -#define LEDS_LIGHT_BLUE (LEDS_GREEN | LEDS_BLUE) /**< Green + Blue (24) */ -#define LEDS_YELLOW (LEDS_GREEN | LEDS_RED) /**< Green + Red (48) */ -#define LEDS_PURPLE (LEDS_BLUE | LEDS_RED) /**< Blue + Red (40) */ -#define LEDS_WHITE LEDS_ALL /**< Green + Blue + Red (56) */ - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 3 /** @} */ /*---------------------------------------------------------------------------*/ /** \name USB configuration diff --git a/arch/platform/zoul/remote-revb/Makefile.remote-revb b/arch/platform/zoul/remote-revb/Makefile.remote-revb index d23362c32b01b19d1538e42e5eb1927df0a3283f..fcccdf0f477fe5fe92a875a6c0b7f1db2dd2ac51 100644 --- a/arch/platform/zoul/remote-revb/Makefile.remote-revb +++ b/arch/platform/zoul/remote-revb/Makefile.remote-revb @@ -1,4 +1,4 @@ MOTELIST_ZOLERTIA = remote -BOARD_SOURCEFILES += board.c antenna-sw.c mmc-arch.c rtcc.c leds-res-arch.c power-mgmt.c +BOARD_SOURCEFILES += board.c antenna-sw.c mmc-arch.c rtcc.c power-mgmt.c MODULES += os/lib/fs/fat os/lib/fs/fat/option arch/platform/zoul/fs/fat arch/dev/disk/mmc diff --git a/arch/platform/zoul/remote-revb/board.h b/arch/platform/zoul/remote-revb/board.h index fb50f13dc35aa547cd728dd6e8bab01e7ae08c60..244489562fa17e40daca61d39c374d412907f181 100644 --- a/arch/platform/zoul/remote-revb/board.h +++ b/arch/platform/zoul/remote-revb/board.h @@ -105,32 +105,18 @@ * @{ */ /*---------------------------------------------------------------------------*/ -#undef LEDS_GREEN -#undef LEDS_YELLOW -#undef LEDS_BLUE -#undef LEDS_RED -#undef LEDS_CONF_ALL +#define LEDS_ARCH_L1_PORT GPIO_D_NUM +#define LEDS_ARCH_L1_PIN 4 +#define LEDS_ARCH_L2_PORT GPIO_B_NUM +#define LEDS_ARCH_L2_PIN 7 +#define LEDS_ARCH_L3_PORT GPIO_B_NUM +#define LEDS_ARCH_L3_PIN 6 -#define LEDS_RED 1 /**< LED1 (Red) -> PD4 */ -#define LEDS_RED_PIN_MASK (1 << 4) -#define LEDS_RED_PORT_BASE GPIO_D_BASE +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_BLUE 4 -#define LEDS_GREEN 2 /**< LED2 (Green) -> PB7 */ -#define LEDS_GREEN_PIN_MASK (1 << 7) -#define LEDS_GREEN_PORT_BASE GPIO_B_BASE - -#define LEDS_BLUE 4 /**< LED3 (Blue) -> PB6 */ -#define LEDS_BLUE_PIN_MASK (1 << 6) -#define LEDS_BLUE_PORT_BASE GPIO_B_BASE - -#define LEDS_CONF_ALL (LEDS_GREEN | LEDS_BLUE | LEDS_RED) /* 7 */ -#define LEDS_LIGHT_BLUE (LEDS_GREEN | LEDS_BLUE) /* 6 */ -#define LEDS_YELLOW (LEDS_GREEN | LEDS_RED) /* 3 */ -#define LEDS_PURPLE (LEDS_BLUE | LEDS_RED) /* 5 */ -#define LEDS_WHITE LEDS_ALL /* 7 */ - -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_COUNT 3 /** @} */ /*---------------------------------------------------------------------------*/ /** \name USB configuration diff --git a/arch/platform/zoul/remote-revb/leds-res-arch.c b/arch/platform/zoul/remote-revb/leds-res-arch.c deleted file mode 100644 index 59484c2ffa77e53eeb7c6f1bff661124c67ff6ed..0000000000000000000000000000000000000000 --- a/arch/platform/zoul/remote-revb/leds-res-arch.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2015, Zolertia - http://www.zolertia.com - * Copyright (c) 2015, University of Bristol - http://www.bristol.ac.uk - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \addtogroup zoul - * @{ - * - * \defgroup remote-revb-leds RE-Mote revision B arch LED - * - * LED driver implementation for the RE-Mote revision B - * @{ - * - * \file - * LED driver implementation for the RE-Mote revision B - */ -#include "contiki.h" -#include "reg.h" -#include "dev/leds.h" -#include "dev/gpio.h" -#include "dev/ioc.h" -/*---------------------------------------------------------------------------*/ -#define LEDS_PORTB_PIN_MASK (LEDS_GREEN_PIN_MASK | LEDS_BLUE_PIN_MASK) -/*---------------------------------------------------------------------------*/ -void -leds_arch_init(void) -{ - /* Initialize LED2 (Green) and LED3 (Blue) */ - GPIO_SOFTWARE_CONTROL(GPIO_B_BASE, LEDS_PORTB_PIN_MASK); - GPIO_SET_OUTPUT(GPIO_B_BASE, LEDS_PORTB_PIN_MASK); - GPIO_CLR_PIN(GPIO_B_BASE, LEDS_PORTB_PIN_MASK); - - /* Initialize LED1 (Red) */ - GPIO_SOFTWARE_CONTROL(LEDS_RED_PORT_BASE, LEDS_RED_PIN_MASK); - GPIO_SET_OUTPUT(LEDS_RED_PORT_BASE, LEDS_RED_PIN_MASK); - GPIO_CLR_PIN(LEDS_RED_PORT_BASE, LEDS_RED_PIN_MASK); -} -/*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - uint8_t mask_leds; - - mask_leds = GPIO_READ_PIN(LEDS_GREEN_PORT_BASE, LEDS_GREEN_PIN_MASK) == 0 ? 0: LEDS_GREEN; - mask_leds |= GPIO_READ_PIN(LEDS_BLUE_PORT_BASE, LEDS_BLUE_PIN_MASK) == 0 ? 0 : LEDS_BLUE; - mask_leds |= GPIO_READ_PIN(LEDS_RED_PORT_BASE, LEDS_RED_PIN_MASK) == 0 ? 0 : LEDS_RED; - - return mask_leds; -} -/*---------------------------------------------------------------------------*/ -void -leds_arch_set(unsigned char leds) -{ - if(leds & LEDS_GREEN) { - GPIO_SET_PIN(LEDS_GREEN_PORT_BASE, LEDS_GREEN_PIN_MASK); - } else { - GPIO_CLR_PIN(LEDS_GREEN_PORT_BASE, LEDS_GREEN_PIN_MASK); - } - - if(leds & LEDS_BLUE) { - GPIO_SET_PIN(LEDS_BLUE_PORT_BASE, LEDS_BLUE_PIN_MASK); - } else { - GPIO_CLR_PIN(LEDS_BLUE_PORT_BASE, LEDS_BLUE_PIN_MASK); - } - - if(leds & LEDS_RED) { - GPIO_SET_PIN(LEDS_RED_PORT_BASE, LEDS_RED_PIN_MASK); - } else { - GPIO_CLR_PIN(LEDS_RED_PORT_BASE, LEDS_RED_PIN_MASK); - } -} -/*---------------------------------------------------------------------------*/ -/** - * @} - * @} - */ diff --git a/examples/6tisch/6p-packet/6p-packet.csc b/examples/6tisch/6p-packet/6p-packet.csc index 9f1bfe534ce092dda125be9d00ff218684cc861c..e25b08ef8d293221018a086b9390cc0563982803 100644 --- a/examples/6tisch/6p-packet/6p-packet.csc +++ b/examples/6tisch/6p-packet/6p-packet.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> diff --git a/examples/6tisch/6p-packet/Makefile b/examples/6tisch/6p-packet/Makefile index 1ae6e34b5a5bc74eb4b7065507ca5e35b2d6ce34..7dcf9ccd3c7ed15796de7f8d18fda614bbbfc712 100644 --- a/examples/6tisch/6p-packet/Makefile +++ b/examples/6tisch/6p-packet/Makefile @@ -1,10 +1,14 @@ -CONTIKI_PROJECT = sixp-node.c +CONTIKI_PROJECT = sixp-node PROJECT_SOURCEFILES += test-sf.c +PLATFORMS_EXCLUDE = sky nrf52dk native +BOARDS_EXCLUDE = srf06/cc13xx launchpad/cc1310 launchpad/cc1350 sensortag/cc2650 sensortag/cc1350 + CONTIKI = ../../../ MAKE_MAC = MAKE_MAC_TSCH -MAKE_ROUTING = MAKE_ROUTING_NONE +MAKE_ROUTING = MAKE_ROUTING_NULLROUTING MODULES += os/net/mac/tsch/sixtop +all: $(CONTIKI_PROJECT) include $(CONTIKI)/Makefile.include diff --git a/examples/6tisch/6p-packet/project-conf.h b/examples/6tisch/6p-packet/project-conf.h index 1e8fc03e0e8b6ce86cf0268388689d024d237eae..9771fe4b14e780c679488fb62c63550fa04283bc 100644 --- a/examples/6tisch/6p-packet/project-conf.h +++ b/examples/6tisch/6p-packet/project-conf.h @@ -28,8 +28,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _PROJECT_CONF_H_ -#define _PROJECT_CONF_H_ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ #define UIP_CONF_ND6_SEND_RA 0 @@ -37,4 +37,6 @@ #define TSCH_CONF_AUTOSTART 1 #define TSCH_CONF_DEFAULT_HOPPING_SEQUENCE TSCH_HOPPING_SEQUENCE_1_1 -#endif /* _PROJECT_CONF_H_ */ +#define LOG_CONF_LEVEL_6TOP LOG_LEVEL_DBG + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/6tisch/6p-packet/sixp-node.c b/examples/6tisch/6p-packet/sixp-node.c index d911701bc44ec8e69d847f549a7da7a9fa1209ee..7bcc8a1a997337f9989e87b5375a54d946956850 100644 --- a/examples/6tisch/6p-packet/sixp-node.c +++ b/examples/6tisch/6p-packet/sixp-node.c @@ -30,26 +30,27 @@ #include <contiki.h> #include <lib/assert.h> -#include <sys/node-id.h> #include <net/mac/tsch/tsch.h> #include <net/mac/tsch/tsch-queue.h> #include <net/mac/tsch/sixtop/sixtop.h> +/* Hard-coded MAC address of the TSCH coordinator */ +static linkaddr_t coordinator_addr = {{ 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x01 }}; + extern const sixtop_sf_t test_sf; extern int test_sf_start(const linkaddr_t *addr); PROCESS(sixp_node_process, "6P node"); AUTOSTART_PROCESSES(&sixp_node_process); -#define COORDINATOR_NODE_ID 1 - PROCESS_THREAD(sixp_node_process, ev, data) { PROCESS_BEGIN(); sixtop_add_sf(&test_sf); - if(node_id == COORDINATOR_NODE_ID) { + if(linkaddr_cmp(&coordinator_addr, &linkaddr_node_addr)) { tsch_set_coordinator(1); assert(test_sf_start(NULL) == 0); } else { diff --git a/examples/6tisch/6p-packet/test-sf.c b/examples/6tisch/6p-packet/test-sf.c index 05418698401034d9d6f6370c3a3f0d7f647b278f..e8745edaedc59a5aa007f84c9c92a450c98bef9f 100644 --- a/examples/6tisch/6p-packet/test-sf.c +++ b/examples/6tisch/6p-packet/test-sf.c @@ -30,7 +30,7 @@ #include <contiki.h> #include <lib/assert.h> -#include <net/mac/tsch/tsch-queue.h> +#include <net/mac/tsch/tsch.h> #include <net/mac/tsch/sixtop/sixtop.h> #include <net/mac/tsch/sixtop/sixp.h> #include <net/mac/tsch/sixtop/sixp-nbr.h> @@ -67,16 +67,17 @@ static void test_relocate_2_step(const linkaddr_t *peer_addr); static void test_count_2_step(const linkaddr_t *peer_addr); static void test_list_2_step(const linkaddr_t *peer_addr); static void test_list_2_step_eol(const linkaddr_t *peer_addr); +static void test_signal_2_step(const linkaddr_t *peer_addr); static void test_clear_2_step_success(const linkaddr_t *peer_addr); -static void test_clear_2_step_error(const linkaddr_t *peer_addr); static void test_clear_2_step_eol(const linkaddr_t *peer_addr); +static void test_clear_2_step_err(const linkaddr_t *peer_addr); static void test_clear_2_step_reset(const linkaddr_t *peer_addr); static void test_clear_2_step_version(const linkaddr_t *peer_addr); static void test_clear_2_step_sfid(const linkaddr_t *peer_addr); -static void test_clear_2_step_gen(const linkaddr_t *peer_addr); -static void test_clear_2_step_busy(const linkaddr_t *peer_addr); -static void test_clear_2_step_nores(const linkaddr_t *peer_addr); +static void test_clear_2_step_seqnum(const linkaddr_t *peer_addr); static void test_clear_2_step_celllist(const linkaddr_t *peer_addr); +static void test_clear_2_step_busy(const linkaddr_t *peer_addr); +static void test_clear_2_step_locked(const linkaddr_t *peer_addr); typedef void (*test_func)(const linkaddr_t *peer_addr); static const test_func test_case[] = { @@ -88,27 +89,19 @@ static const test_func test_case[] = { test_count_2_step, test_list_2_step, test_list_2_step_eol, + test_signal_2_step, test_clear_2_step_success, - test_clear_2_step_error, test_clear_2_step_eol, + test_clear_2_step_err, test_clear_2_step_reset, test_clear_2_step_version, test_clear_2_step_sfid, - test_clear_2_step_gen, - test_clear_2_step_busy, - test_clear_2_step_nores, + test_clear_2_step_seqnum, test_clear_2_step_celllist, + test_clear_2_step_busy, + test_clear_2_step_locked, }; -static void -advance_gen(const linkaddr_t *peer_addr) -{ - sixp_nbr_t *nbr; - nbr = sixp_nbr_find(peer_addr); - assert(nbr != NULL); - assert(sixp_nbr_advance_gen(nbr) == 0); -} - static void set_peer_addr(const linkaddr_t *addr) { @@ -202,10 +195,8 @@ test_add_2_step(const linkaddr_t *peer_addr) peer_addr, NULL, NULL, 0); test_index++; - advance_gen(peer_addr); } else if(state == SIXP_TRANS_STATE_RESPONSE_RECEIVED) { process_post(&test_sf_process, test_sf_trans_done, NULL); - advance_gen(peer_addr); } } } @@ -266,10 +257,8 @@ test_add_3_step(const linkaddr_t *peer_addr) peer_addr, NULL, NULL, 0); process_post(&test_sf_process, test_sf_trans_done, NULL); - advance_gen(peer_addr); } else if (state == SIXP_TRANS_STATE_CONFIRMATION_RECEIVED){ test_index++; - advance_gen(peer_addr); } } } @@ -325,10 +314,8 @@ test_delete_2_step(const linkaddr_t *peer_addr) peer_addr, NULL, NULL, 0); test_index++; - advance_gen(peer_addr); } else if(state == SIXP_TRANS_STATE_RESPONSE_RECEIVED) { process_post(&test_sf_process, test_sf_trans_done, NULL); - advance_gen(peer_addr); } } } @@ -390,10 +377,8 @@ test_delete_3_step(const linkaddr_t *peer_addr) peer_addr, NULL, NULL, 0); process_post(&test_sf_process, test_sf_trans_done, NULL); - advance_gen(peer_addr); } else if (state == SIXP_TRANS_STATE_CONFIRMATION_RECEIVED) { test_index++; - advance_gen(peer_addr); } } } @@ -459,10 +444,8 @@ test_relocate_2_step(const linkaddr_t *peer_addr) peer_addr, NULL, NULL, 0); test_index++; - advance_gen(peer_addr); } else if(state == SIXP_TRANS_STATE_RESPONSE_RECEIVED) { process_post(&test_sf_process, test_sf_trans_done, NULL); - advance_gen(peer_addr); } } } @@ -658,6 +641,70 @@ test_list_2_step_eol(const linkaddr_t *peer_addr) } } +static void +test_signal_2_step(const linkaddr_t *peer_addr) +{ + sixp_trans_t *trans = sixp_trans_find(peer_addr); + uint8_t payload[10]; + size_t payload_len; + + if(trans == NULL) { + memset(sixp_pkt_buf, 0, sizeof(sixp_pkt_buf)); + assert( + sixp_pkt_set_metadata(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_LIST, + sample_metadata, + sixp_pkt_buf, sizeof(sixp_pkt_buf)) == 0); + + payload[0] = 0xbe; + payload[1] = 0xef; + payload[2] = 0xca; + payload[3] = 0xfe; + payload_len = 4; + + assert( + sixp_pkt_set_payload(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + (const uint8_t *)payload, payload_len, + sixp_pkt_buf, sizeof(sixp_pkt_buf)) == 0); + + assert(sixp_output(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + TEST_SF_SFID, sixp_pkt_buf, + sizeof(sixp_pkt_metadata_t) + payload_len, + peer_addr, + NULL, NULL, 0) == 0); + } else { + sixp_trans_state_t state; + printf("hoge\n"); + state = sixp_trans_get_state(trans); + if(state == SIXP_TRANS_STATE_REQUEST_RECEIVED) { + payload[0] = 0x01; + payload[1] = 0x02; + payload[2] = 0x03; + payload[3] = 0x04; + payload[4] = 0x05; + payload_len = 5; + + assert( + sixp_pkt_set_payload(SIXP_PKT_TYPE_RESPONSE, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS, + (const uint8_t *)payload, payload_len, + sixp_pkt_buf, sizeof(sixp_pkt_buf)) == 0); + + sixp_output(SIXP_PKT_TYPE_RESPONSE, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS, + TEST_SF_SFID, sixp_pkt_buf, + payload_len, + peer_addr, + NULL, NULL, 0); + test_index++; + } else if(state == SIXP_TRANS_STATE_RESPONSE_RECEIVED) { + process_post(&test_sf_process, test_sf_trans_done, NULL); + } + } +} + static void test_clear_2_step(const linkaddr_t *peer_addr, sixp_pkt_rc_t rc) { @@ -699,9 +746,9 @@ test_clear_2_step_success(const linkaddr_t *peer_addr) } static void -test_clear_2_step_error(const linkaddr_t *peer_addr) +test_clear_2_step_err(const linkaddr_t *peer_addr) { - test_clear_2_step(peer_addr, SIXP_PKT_RC_ERROR); + test_clear_2_step(peer_addr, SIXP_PKT_RC_ERR); } static void @@ -719,37 +766,37 @@ test_clear_2_step_reset(const linkaddr_t *peer_addr) static void test_clear_2_step_version(const linkaddr_t *peer_addr) { - test_clear_2_step(peer_addr, SIXP_PKT_RC_VERSION); + test_clear_2_step(peer_addr, SIXP_PKT_RC_ERR_VERSION); } static void test_clear_2_step_sfid(const linkaddr_t *peer_addr) { - test_clear_2_step(peer_addr, SIXP_PKT_RC_SFID); + test_clear_2_step(peer_addr, SIXP_PKT_RC_ERR_SFID); } static void -test_clear_2_step_gen(const linkaddr_t *peer_addr) +test_clear_2_step_seqnum(const linkaddr_t *peer_addr) { - test_clear_2_step(peer_addr, SIXP_PKT_RC_GEN); + test_clear_2_step(peer_addr, SIXP_PKT_RC_ERR_SEQNUM); } static void test_clear_2_step_busy(const linkaddr_t *peer_addr) { - test_clear_2_step(peer_addr, SIXP_PKT_RC_BUSY); + test_clear_2_step(peer_addr, SIXP_PKT_RC_ERR_BUSY); } static void -test_clear_2_step_nores(const linkaddr_t *peer_addr) +test_clear_2_step_locked(const linkaddr_t *peer_addr) { - test_clear_2_step(peer_addr, SIXP_PKT_RC_NORES); + test_clear_2_step(peer_addr, SIXP_PKT_RC_ERR_LOCKED); } static void test_clear_2_step_celllist(const linkaddr_t *peer_addr) { - test_clear_2_step(peer_addr, SIXP_PKT_RC_CELLLIST); + test_clear_2_step(peer_addr, SIXP_PKT_RC_ERR_CELLLIST); } PROCESS_THREAD(test_sf_process, ev, data) diff --git a/examples/6tisch/etsi-plugtest-2017/Makefile b/examples/6tisch/etsi-plugtest-2017/Makefile index f09edc0a74fa860499ac51b0a157c32a6d581255..3279b6ebc38f8f0629919474ad31474834ec20c3 100644 --- a/examples/6tisch/etsi-plugtest-2017/Makefile +++ b/examples/6tisch/etsi-plugtest-2017/Makefile @@ -1,6 +1,9 @@ CONTIKI_PROJECT = node all: $(CONTIKI_PROJECT) +PLATFORMS_EXCLUDE = sky nrf52dk native +BOARDS_EXCLUDE = srf06/cc13xx launchpad/cc1310 launchpad/cc1350 sensortag/cc2650 sensortag/cc1350 + MAKE_WITH_SECURITY ?= 0 # force Security from command line ifeq ($(MAKE_WITH_SECURITY),1) CFLAGS += -DWITH_SECURITY=1 diff --git a/examples/6tisch/etsi-plugtest-2017/node.c b/examples/6tisch/etsi-plugtest-2017/node.c index 578727d1f082463a8ef27e35fbf98bc01df59825..3046bb29181b93550cf678543bd09afb47f9659f 100644 --- a/examples/6tisch/etsi-plugtest-2017/node.c +++ b/examples/6tisch/etsi-plugtest-2017/node.c @@ -38,15 +38,10 @@ #include "contiki.h" #include "node-id.h" -#include "rpl.h" -#include "rpl-dag-root.h" #include "sys/log.h" #include "net/ipv6/uip-ds6-route.h" #include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-log.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ +#include "net/routing/routing.h" #include "serial-shell.h" #include "sf-plugtest.h" #if CONTIKI_TARGET_SRF06_CC26XX @@ -81,7 +76,7 @@ PROCESS_THREAD(node_process, ev, data) #endif if(is_coordinator) { - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_start(); } NETSTACK_MAC.on(); diff --git a/examples/6tisch/etsi-plugtest-2017/project-conf.h b/examples/6tisch/etsi-plugtest-2017/project-conf.h index 751ccf9777d7dd24cdcc0c7a95953ce9ee2901b8..93c5925b6dadb1394bf57871a85411c6c9299eca 100644 --- a/examples/6tisch/etsi-plugtest-2017/project-conf.h +++ b/examples/6tisch/etsi-plugtest-2017/project-conf.h @@ -32,8 +32,8 @@ * \author Simon Duquennoy <simonduq@sics.se> */ -#ifndef __PROJECT_CONF_H__ -#define __PROJECT_CONF_H__ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ /* Set to enable TSCH security */ #ifndef WITH_SECURITY @@ -101,12 +101,6 @@ #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_6LORH -/*******************************************************/ -/********* Enable RPL non-storing mode *****************/ -/*******************************************************/ - -#define RPL_CONF_MOP RPL_MOP_NON_STORING /* Mode of operation*/ - /*******************************************************/ /************* Other system configuration **************/ /*******************************************************/ @@ -121,6 +115,4 @@ #define LOG_CONF_LEVEL_6TOP LOG_LEVEL_DBG #define TSCH_LOG_CONF_PER_SLOT 1 -#define TCPIP_CONF_ANNOTATE_TRANSMISSIONS 0 - -#endif /* __PROJECT_CONF_H__ */ +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/6tisch/etsi-plugtest-2017/sf-plugtest.c b/examples/6tisch/etsi-plugtest-2017/sf-plugtest.c index 8c6628f3fe3ce23df1913112953d565f785eeb1a..406178d713d20fb865c3d0ddf59c582e7b60e3be 100644 --- a/examples/6tisch/etsi-plugtest-2017/sf-plugtest.c +++ b/examples/6tisch/etsi-plugtest-2017/sf-plugtest.c @@ -75,7 +75,6 @@ typedef void (req_handler_t)(const linkaddr_t *peer_addr, typedef void (res_handler_t)(const linkaddr_t *peer_addr, sixp_pkt_rc_t rc, const uint8_t *body, size_t body_len); -static void advance_gen(const linkaddr_t *peer_addr); static void add_res_sent_callback(void *arg, uint16_t arg_len, const linkaddr_t *dest_addr, sixp_output_status_t status); @@ -145,17 +144,6 @@ static const struct { { SIXP_PKT_CMD_UNAVAILABLE, NULL, NULL } }; -static void -advance_gen(const linkaddr_t *peer_addr) -{ - sixp_nbr_t *nbr; - assert((nbr = sixp_nbr_find(peer_addr)) != NULL); - if(nbr == NULL) { - return; - } - assert(sixp_nbr_advance_gen(nbr) == 0); -} - static void add_res_sent_callback(void *arg, uint16_t arg_len, const linkaddr_t *dest_addr, @@ -168,7 +156,6 @@ add_res_sent_callback(void *arg, uint16_t arg_len, } else { add_cell(dest_addr, (sf_plugtest_cell_t *)arg, LINK_OPTION_RX); } - advance_gen(dest_addr); } static void @@ -182,7 +169,6 @@ delete_res_sent_callback(void *arg, uint16_t arg_len, LOG_ERR("error in sending a response\n"); } else { delete_cell(dest_addr, (sf_plugtest_cell_t *)arg); - advance_gen(dest_addr); } } @@ -314,7 +300,7 @@ add_req_handler(const linkaddr_t *peer_addr, sizeof(sixp_pkt_cell_options_t) + sizeof(sixp_pkt_num_cells_t) + sizeof(sf_plugtest_cell_t))) { - LOG_ERR("invalid Add Request length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid Add Request length: %lu\n", (unsigned long)body_len); } assert( sixp_pkt_get_cell_options(SIXP_PKT_TYPE_REQUEST, @@ -338,7 +324,7 @@ add_req_handler(const linkaddr_t *peer_addr, reserve_cell(peer_addr, &pending_cell) < 0) { LOG_ERR("Failed to add a cell [slot:%u]\n", timeslot); sixp_output(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_NORES, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR_BUSY, SF_PLUGTEST_SFID, NULL, 0, peer_addr, NULL, NULL, 0); } else { @@ -359,7 +345,7 @@ add_res_handler(const linkaddr_t *peer_addr, sixp_pkt_rc_t rc, struct tsch_slotframe *slotframe; if(body_len != 4) { - LOG_ERR("invalid Add Response length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid Add Response length: %lu\n", (unsigned long)body_len); return; } @@ -378,7 +364,6 @@ add_res_handler(const linkaddr_t *peer_addr, sixp_pkt_rc_t rc, add_cell(peer_addr, (sf_plugtest_cell_t *)cell, LINK_OPTION_TX) < 0) { LOG_ERR("Failed to add a cell [slot:%u]\n", timeslot); } - advance_gen(peer_addr); } static void @@ -399,7 +384,7 @@ delete_req_handler(const linkaddr_t *peer_addr, sizeof(sixp_pkt_cell_options_t) + sizeof(sixp_pkt_num_cells_t) + sizeof(sf_plugtest_cell_t))) { - LOG_ERR("invalid Delete Request length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid Delete Request length: %lu\n", (unsigned long)body_len); } assert( sixp_pkt_get_cell_options(SIXP_PKT_TYPE_REQUEST, @@ -423,7 +408,7 @@ delete_req_handler(const linkaddr_t *peer_addr, memcmp(peer_addr, &link->addr, sizeof(linkaddr_t)) != 0) { LOG_ERR("Failed to delete a cell [slot:%u]\n", timeslot); sixp_output(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_NORES, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR_BUSY, SF_PLUGTEST_SFID, NULL, 0, peer_addr, NULL, NULL, 0); } else { @@ -446,7 +431,7 @@ delete_res_handler(const linkaddr_t *peer_addr, sixp_pkt_rc_t rc, uint16_t timeslot; if(body_len != 4) { - LOG_ERR("invalid Delete Response length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid Delete Response length: %lu\n", (unsigned long)body_len); return; } @@ -473,7 +458,6 @@ delete_res_handler(const linkaddr_t *peer_addr, sixp_pkt_rc_t rc, delete_cell(peer_addr, cell) < 0) { LOG_ERR("Failed to delete a cell [slot:%u]\n", timeslot); } - advance_gen(peer_addr); } static void @@ -489,7 +473,7 @@ count_req_handler(const linkaddr_t *peer_addr, assert(peer_addr != NULL && body != NULL); if(body_len != (sizeof(sixp_pkt_metadata_t) + sizeof(sixp_pkt_cell_options_t))) { - LOG_ERR("invalid Count Request length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid Count Request length: %lu\n", (unsigned long)body_len); } assert( sixp_pkt_get_cell_options(SIXP_PKT_TYPE_REQUEST, @@ -503,7 +487,7 @@ count_req_handler(const linkaddr_t *peer_addr, if((slotframe = tsch_schedule_get_slotframe_by_handle(0)) == NULL) { sixp_output(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, SF_PLUGTEST_SFID, NULL, 0, peer_addr, NULL, NULL, 0); return; @@ -534,7 +518,7 @@ count_res_handler(const linkaddr_t *peer_addr, sixp_pkt_rc_t rc, sixp_pkt_total_num_cells_t total_num_cells; if(body_len != 2) { - LOG_ERR("invalid Count Response length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid Count Response length: %lu\n", (unsigned long)body_len); return; } @@ -570,7 +554,7 @@ list_req_handler(const linkaddr_t *peer_addr, sizeof(sixp_pkt_reserved_t) + sizeof(sixp_pkt_offset_t) + sizeof(sixp_pkt_max_num_cells_t))) { - LOG_ERR("invalid List Request length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid List Request length: %lu\n", (unsigned long)body_len); } assert( @@ -602,7 +586,7 @@ list_req_handler(const linkaddr_t *peer_addr, if((slotframe = tsch_schedule_get_slotframe_by_handle(0)) == NULL) { sixp_output(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, SF_PLUGTEST_SFID, NULL, 0, peer_addr, NULL, NULL, 0); return; @@ -679,12 +663,12 @@ clear_req_handler(const linkaddr_t *peer_addr, assert(peer_addr != NULL && body != NULL); if(body_len != sizeof(sixp_pkt_metadata_t)) { - LOG_ERR("invalid Clear Request length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid Clear Request length: %lu\n", (unsigned long)body_len); } if((slotframe = tsch_schedule_get_slotframe_by_handle(0)) == NULL) { sixp_output(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, SF_PLUGTEST_SFID, NULL, 0, peer_addr, NULL, NULL, 0); return; @@ -717,7 +701,7 @@ clear_res_handler(const linkaddr_t *peer_addr, sixp_pkt_rc_t rc, } if(body_len != 0) { - LOG_ERR("invalid Clear Response length: %u\n", (unsigned int)body_len); + LOG_ERR("invalid Clear Response length: %lu\n", (unsigned long)body_len); return; } diff --git a/examples/6tisch/etsi-plugtest-2017/test-with-cooja-mote.csc b/examples/6tisch/etsi-plugtest-2017/test-with-cooja-mote.csc index fda05987f2e2b87b780062cbc1be3ec15c634793..e1102b2fa787675dbac7db943c7c3228273e362d 100644 --- a/examples/6tisch/etsi-plugtest-2017/test-with-cooja-mote.csc +++ b/examples/6tisch/etsi-plugtest-2017/test-with-cooja-mote.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <project EXPORT="discard">[APPS_DIR]/radiologger-headless</project> <simulation> diff --git a/examples/6tisch/simple-node/Makefile b/examples/6tisch/simple-node/Makefile index e6cb76944e94693f3e179a3e56709b3e9f8159b5..63ce8ecbdc5bedab9197735976e1ab4ec40c8792 100644 --- a/examples/6tisch/simple-node/Makefile +++ b/examples/6tisch/simple-node/Makefile @@ -1,11 +1,17 @@ CONTIKI_PROJECT = node all: $(CONTIKI_PROJECT) +PLATFORMS_EXCLUDE = sky nrf52dk native +BOARDS_EXCLUDE = srf06/cc13xx launchpad/cc1310 launchpad/cc1350 sensortag/cc2650 sensortag/cc1350 + CONTIKI=../../.. -MAKE_WITH_ORCHESTRA ?= 0 # force Orchestra from command line -MAKE_WITH_SECURITY ?= 0 # force Security from command line -MAKE_WITH_PERIODIC_ROUTES_PRINT ?= 0 # print #routes periodically, used for regression tests + # force Orchestra from command line +MAKE_WITH_ORCHESTRA ?= 0 +# force Security from command line +MAKE_WITH_SECURITY ?= 0 + # print #routes periodically, used for regression tests +MAKE_WITH_PERIODIC_ROUTES_PRINT ?= 0 MAKE_MAC = MAKE_MAC_TSCH MODULES += os/services/shell diff --git a/examples/6tisch/simple-node/node.c b/examples/6tisch/simple-node/node.c index 9884b4e0e15a4d24882efb37bc8b60e4c5cd5985..d2f75ae33d94fd9504918e520272d8fe49bca287 100644 --- a/examples/6tisch/simple-node/node.c +++ b/examples/6tisch/simple-node/node.c @@ -38,15 +38,11 @@ #include "contiki.h" #include "node-id.h" -#include "rpl.h" -#include "rpl-dag-root.h" #include "sys/log.h" #include "net/ipv6/uip-ds6-route.h" +#include "net/ipv6/uip-sr.h" #include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-log.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ +#include "net/routing/routing.h" #define DEBUG DEBUG_PRINT #include "net/ipv6/uip-debug.h" @@ -69,7 +65,7 @@ PROCESS_THREAD(node_process, ev, data) #endif if(is_coordinator) { - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_start(); } NETSTACK_MAC.on(); @@ -80,11 +76,11 @@ PROCESS_THREAD(node_process, ev, data) etimer_set(&et, CLOCK_SECOND * 60); while(1) { /* Used for non-regression testing */ - #if RPL_WITH_STORING + #if (UIP_MAX_ROUTES != 0) PRINTF("Routing entries: %u\n", uip_ds6_route_num_routes()); #endif - #if RPL_WITH_NON_STORING - PRINTF("Routing links: %u\n", rpl_ns_num_nodes()); + #if (UIP_SR_LINK_NUM != 0) + PRINTF("Routing links: %u\n", uip_sr_num_nodes()); #endif PROCESS_YIELD_UNTIL(etimer_expired(&et)); etimer_reset(&et); diff --git a/examples/6tisch/simple-node/project-conf.h b/examples/6tisch/simple-node/project-conf.h index a46792fea43e1ba67e470a6f939a126db961c4ab..3771fb50f3147c6c7397eee39db0eda065e179f5 100644 --- a/examples/6tisch/simple-node/project-conf.h +++ b/examples/6tisch/simple-node/project-conf.h @@ -32,20 +32,14 @@ * \author Simon Duquennoy <simonduq@sics.se> */ -#ifndef __PROJECT_CONF_H__ -#define __PROJECT_CONF_H__ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ /* Set to enable TSCH security */ #ifndef WITH_SECURITY #define WITH_SECURITY 0 #endif /* WITH_SECURITY */ -/*******************************************************/ -/********* Enable RPL non-storing mode *****************/ -/*******************************************************/ - -#define RPL_CONF_MOP RPL_MOP_NON_STORING /* Mode of operation*/ - /* USB serial takes space, free more space elsewhere */ #define SICSLOWPAN_CONF_FRAG 0 #define UIP_CONF_BUFFER_SIZE 160 @@ -84,4 +78,4 @@ #define LOG_CONF_LEVEL_FRAMER LOG_LEVEL_DBG #define TSCH_LOG_CONF_PER_SLOT 1 -#endif /* __PROJECT_CONF_H__ */ +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/6tisch/simple-node/rpl-tsch-cooja.csc b/examples/6tisch/simple-node/rpl-tsch-cooja.csc index 276192cddac6a3879bb0a3e16a6ea1bb5d71ce92..bd5557214c1e61129db63c41c21b86135f54dd6a 100644 --- a/examples/6tisch/simple-node/rpl-tsch-cooja.csc +++ b/examples/6tisch/simple-node/rpl-tsch-cooja.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <project EXPORT="discard">[APPS_DIR]/radiologger-headless</project> <simulation> diff --git a/examples/6tisch/sixtop/Makefile b/examples/6tisch/sixtop/Makefile index 42360f170473569fad4c10180ff23878002fb0c9..5ca6be8530cd5d1daa9abd88b41f82c906d0a8a4 100644 --- a/examples/6tisch/sixtop/Makefile +++ b/examples/6tisch/sixtop/Makefile @@ -1,6 +1,9 @@ CONTIKI_PROJECT = node-sixtop all: $(CONTIKI_PROJECT) +PLATFORMS_EXCLUDE = sky nrf52dk native +BOARDS_EXCLUDE = srf06/cc13xx launchpad/cc1310 launchpad/cc1350 sensortag/cc2650 sensortag/cc1350 + PROJECT_SOURCEFILES += sf-simple.c CONTIKI=../../.. diff --git a/examples/6tisch/sixtop/node-sixtop.c b/examples/6tisch/sixtop/node-sixtop.c index 4c60db3a704aaf291ff7c13b0712e9702e945750..67bee378a2bff8804136ce8ac3c5d567794bb424 100755 --- a/examples/6tisch/sixtop/node-sixtop.c +++ b/examples/6tisch/sixtop/node-sixtop.c @@ -39,17 +39,11 @@ #include "contiki.h" #include "node-id.h" -#include "rpl.h" -#include "rpl-dag-root.h" #include "sys/log.h" #include "net/ipv6/uip-ds6-route.h" #include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-log.h" -#include "net/mac/tsch/tsch-schedule.h" #include "net/mac/tsch/sixtop/sixtop.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ +#include "net/routing/routing.h" #include "sf-simple.h" @@ -77,7 +71,7 @@ PROCESS_THREAD(node_process, ev, data) #endif if(is_coordinator) { - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_start(); } NETSTACK_MAC.on(); diff --git a/examples/6tisch/sixtop/project-conf.h b/examples/6tisch/sixtop/project-conf.h index ff8b96ad7f08cccba8e97092e18502b067ffa11d..5235353c234affb25b287acc404fda32bfa6e379 100755 --- a/examples/6tisch/sixtop/project-conf.h +++ b/examples/6tisch/sixtop/project-conf.h @@ -28,20 +28,14 @@ * */ -#ifndef __PROJECT_CONF_H__ -#define __PROJECT_CONF_H__ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ /* Set to enable TSCH security */ #ifndef WITH_SECURITY #define WITH_SECURITY 0 #endif /* WITH_SECURITY */ -/*******************************************************/ -/********* Enable RPL non-storing mode *****************/ -/*******************************************************/ -#define UIP_CONF_MAX_ROUTES 0 /* No need for routes */ -#define RPL_CONF_MOP RPL_MOP_NON_STORING /* Mode of operation*/ - /*******************************************************/ /********************* Enable TSCH *********************/ /*******************************************************/ @@ -88,7 +82,7 @@ /* Save some space to fit the limited RAM of the z1 */ #define UIP_CONF_TCP 0 #define QUEUEBUF_CONF_NUM 2 -#define RPL_NS_CONF_LINK_NUM 2 +#define NETSTACK_MAX_ROUTE_ENTRIES 2 #define NBR_TABLE_CONF_MAX_NEIGHBORS 2 #define UIP_CONF_ND6_SEND_NA 0 #define SICSLOWPAN_CONF_FRAG 0 @@ -109,4 +103,4 @@ #endif /* CONTIKI_TARGET_CC2538DK || CONTIKI_TARGET_ZOUL \ || CONTIKI_TARGET_OPENMOTE_CC2538 */ -#endif /* __PROJECT_CONF_H__ */ +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/6tisch/sixtop/rpl-tsch-sixtop-cooja.csc b/examples/6tisch/sixtop/rpl-tsch-sixtop-cooja.csc index c0646919d883ca748fadd40c84186d35540329f5..4ef87592423dc7b765ff0872d009c9e05b1ece6b 100644 --- a/examples/6tisch/sixtop/rpl-tsch-sixtop-cooja.csc +++ b/examples/6tisch/sixtop/rpl-tsch-sixtop-cooja.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>sixtop example</title> diff --git a/examples/6tisch/sixtop/sf-simple.c b/examples/6tisch/sixtop/sf-simple.c index e0ba44f211c509481b9547375d986c5532acf705..689c668e7733e8e67dfc6d3a1030256758377e1c 100644 --- a/examples/6tisch/sixtop/sf-simple.c +++ b/examples/6tisch/sixtop/sf-simple.c @@ -40,7 +40,7 @@ #include "contiki-lib.h" #include "lib/assert.h" -#include "net/mac/tsch/tsch-schedule.h" +#include "net/mac/tsch/tsch.h" #include "net/mac/tsch/sixtop/sixtop.h" #include "net/mac/tsch/sixtop/sixp.h" #include "net/mac/tsch/sixtop/sixp-nbr.h" @@ -198,7 +198,6 @@ add_response_sent_callback(void *arg, uint16_t arg_len, (nbr = sixp_nbr_find(dest_addr)) != NULL) { add_links_to_schedule(dest_addr, LINK_OPTION_RX, cell_list, cell_list_len); - sixp_nbr_advance_gen(nbr); } } @@ -222,7 +221,6 @@ delete_response_sent_callback(void *arg, uint16_t arg_len, body, body_len) == 0 && (nbr = sixp_nbr_find(dest_addr)) != NULL) { remove_links_to_schedule(cell_list, cell_list_len); - sixp_nbr_advance_gen(nbr); } } @@ -429,7 +427,6 @@ response_input(sixp_pkt_rc_t rc, PRINTF("\n"); add_links_to_schedule(peer_addr, LINK_OPTION_TX, cell_list, cell_list_len); - sixp_nbr_advance_gen(nbr); break; case SIXP_PKT_CMD_DELETE: if(sixp_pkt_get_cell_list(SIXP_PKT_TYPE_RESPONSE, @@ -443,7 +440,6 @@ response_input(sixp_pkt_rc_t rc, print_cell_list(cell_list, cell_list_len); PRINTF("\n"); remove_links_to_schedule(cell_list, cell_list_len); - sixp_nbr_advance_gen(nbr); break; case SIXP_PKT_CMD_COUNT: case SIXP_PKT_CMD_LIST: diff --git a/examples/coap/Makefile b/examples/coap/Makefile deleted file mode 100644 index 1c8f2d21eef1ccc556791d989adcd90afb6fcde9..0000000000000000000000000000000000000000 --- a/examples/coap/Makefile +++ /dev/null @@ -1,52 +0,0 @@ -all: coap-example-server coap-example-client -# use target "plugtest-server" explicitly when required - -CONTIKI=../.. - -# automatically build RESTful resources -REST_RESOURCES_DIR = ./resources -ifndef TARGET -REST_RESOURCES_FILES = $(notdir $(shell find $(REST_RESOURCES_DIR) -name '*.c')) -else -ifeq ($(TARGET), native) -REST_RESOURCES_FILES = $(notdir $(shell find $(REST_RESOURCES_DIR) -name '*.c')) -else -REST_RESOURCES_FILES = $(notdir $(shell find $(REST_RESOURCES_DIR) -name '*.c' ! -name 'res-plugtest*')) -endif -endif - -PROJECTDIRS += $(REST_RESOURCES_DIR) -PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES) - -# Include the CoAP implementation -MODULES += os/net/app-layer/coap - -# optional rules to get assembly -#CUSTOM_RULE_C_TO_OBJECTDIR_O = 1 -#CUSTOM_RULE_S_TO_OBJECTDIR_O = 1 - -include $(CONTIKI)/Makefile.include - -# optional rules to get assembly -#$(OBJECTDIR)/%.o: asmdir/%.S -# $(CC) $(CFLAGS) -MMD -c $< -o $@ -# @$(FINALIZE_DEPENDENCY) -# -#asmdir/%.S: %.c -# $(CC) $(CFLAGS) -MMD -S $< -o $@ - -# border router rules -$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c - (cd $(CONTIKI)/tools && $(MAKE) tunslip6) - -connect-router: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 fd00::1/64 - -connect-router-cooja: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 -p 60001 fd00::1/64 - -connect-router-native: $(CONTIKI)/examples/native-border-router/border-router.native - sudo $(CONTIKI)/examples/native-border-router/border-router.native -a 127.0.0.1 -p 60001 fd00::1/64 - -connect-minimal: - sudo ip address add fdfd::1/64 dev tap0 diff --git a/examples/coap/README.md b/examples/coap/README.md index f74ddfb9e3b3d2d14ac3125a25634641a24d80f7..36ec0b022ec5c5cd36607ae97e1ecf1e07f4e7a4 100644 --- a/examples/coap/README.md +++ b/examples/coap/README.md @@ -1,148 +1,9 @@ -A Quick Introduction to the Erbium (Er) REST Engine -=================================================== +# CoAP examples: client, server, and plugtest serverA Quick Introduction to the Erbium (Er) CoAP Engine -EXAMPLE FILES -------------- +* coap-example-server: A CoAP server example showing how to use the CoAP layer to develop server-side applications. +* coap-example-client: A CoAP client that polls the /actuators/toggle resource every 10 seconds and cycles through 4 resources on button press (target address is hard-coded). +* coap-plugtest-server: The server used for draft compliance testing at ETSI IoT CoAP Plugtests. Erbium (Er) participated in Paris, France, March 2012 and Sophia-Antipolis, France, November 2012 (configured for native). -- coap-example-server.c: A RESTful server example showing how to use the REST - layer to develop server-side applications (at the moment only CoAP is - implemented for the REST Engine). -- coap-example-client.c: A CoAP client that polls the /actuators/toggle resource - every 10 seconds and cycles through 4 resources on button press (target - address is hard-coded). -- plugtest-server.c: The server used for draft compliance testing at ETSI - IoT CoAP Plugtests. Erbium (Er) participated in Paris, France, March 2012 and - Sophia-Antipolis, France, November 2012 (configured for minimal-net). - -PRELIMINARIES -------------- - -- Make sure rpl-border-router has the same stack and fits into mote memory: - You can disable RDC in border-router project-conf.h (not really required as BR keeps radio turned on). - #define NETSTACK_CONF_RDC nullrdc_driver -- Alternatively, you can use the native-border-router together with the slip-radio. -- For convenience, define the Cooja addresses in /etc/hosts - fd00::0212:7401:0001:0101 cooja1 - fd00::0212:7402:0002:0202 cooja2 - ... -- Get the Copper (Cu) CoAP user-agent from - [https://addons.mozilla.org/en-US/firefox/addon/copper-270430](https://addons.mozilla.org/en-US/firefox/addon/copper-270430) -- Optional: Save your target as default target - make TARGET=sky savetarget - -COOJA HOWTO ------------ - -###Server only: - - make TARGET=cooja server-only.csc - -Open new terminal - - make connect-router-cooja - -- Start Copper and discover resources at coap://cooja2:5683/ -- Choose "Click button on Sky 2" from the context menu of mote 2 (server) after - requesting /test/separate -- Do the same when observing /test/event - -###With client: - - make TARGET=cooja server-client.csc - -Open new terminal - - make connect-router-cooja - -- Wait until red LED toggles on mote 2 (server) -- Choose "Click button on Sky 3" from the context menu of mote 3 (client) and - watch serial output - -TMOTES HOWTO ------------- - -###Server: - -1. Connect two Tmote Skys (check with $ make TARGET=sky sky-motelist) - - make TARGET=sky coap-example-server.upload MOTE=2 - make TARGET=sky login MOTE=2 - -2. Press reset button, get address, abort with Ctrl+C: - Line: "Tentative link-local IPv6 address fe80:0000:0000:0000:____:____:____:____" - - cd ../rpl-border-router/ - make TARGET=sky border-router.upload MOTE=1 - make connect-router - - For a BR tty other than USB0: - - make connect-router-port PORT=X - -3. Start Copper and discover resources at: - - coap://[fd00::____:____:____:____]:5683/ - -### Add a client: - -1. Change the hard-coded server address in coap-example-client.c to fd00::____:____:____:____ -2. Connect a third Tmote Sky - - make TARGET=sky coap-example-client.upload MOTE=3 - -MINIMAL-NET HOWTO ------------------ - -With the target minimal-net you can test your CoAP applications without -constraints, i.e., with large buffers, debug output, memory protection, etc. -The plugtest-server is thought for the minimal-net platform, as it requires -an 1280-byte IP buffer and 1024-byte blocks. - - make TARGET=minimal-net plugtest-server - sudo ./plugtest-server.minimal-net - -Open new terminal - - make connect-minimal - -- Start Copper and discover resources at coap://[fdfd::ff:fe00:10]:5683/ -- You can enable the ETSI Plugtest menu in Copper's preferences - -Under Windows/Cygwin, WPCAP might need a patch in -<cygwin>\usr\include\w32api\in6addr.h: - - 21,23c21 - < #ifdef __INSIDE_CYGWIN__ - < uint32_t __s6_addr32[4]; - < #endif - --- - > u_int __s6_addr32[4]; - 36d33 - < #ifdef __INSIDE_CYGWIN__ - 39d35 - < #endif - -DETAILS -------- - -Erbium implements the Proposed Standard of CoAP. Central features are commented -in coap-example-server.c. In general, coap supports: - -- All draft-18 header options -- CON Retransmissions (note COAP_MAX_OPEN_TRANSACTIONS) -- Blockwise Transfers (note REST_MAX_CHUNK_SIZE, see plugtest-server.c for - Block1 uploads) -- Separate Responses (no rest_set_pre_handler() required anymore, note - coap_separate_accept(), _reject(), and _resume()) -- Resource Discovery -- Observing Resources (see EVENT_ and PRERIODIC_RESOURCE, note - COAP_MAX_OBSERVERS) - -TODOs ------ - -- Dedicated Observe buffers -- Optimize message struct variable access (directly access struct without copying) -- Observe client -- Multiple If-Match ETags -- (Message deduplication) +The examples can run either on a real device or as native. +In the latter case, just start the executable with enough permissions (e.g. sudo), and you will then be able to reach the node via tun. +A tutorial for setting up the CoAP server example and querying it is provided on the wiki. diff --git a/examples/coap/coap-example-client/Makefile b/examples/coap/coap-example-client/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1d34409907e0b9db0f8bd8052f450842d4f8e340 --- /dev/null +++ b/examples/coap/coap-example-client/Makefile @@ -0,0 +1,12 @@ +CONTIKI_PROJECT = coap-example-client +# coap-example-observe-client is outdated but will be ported at a later point +all: $(CONTIKI_PROJECT) + +# Do not try to build on Sky because of code size limitation +PLATFORMS_EXCLUDE = sky + +# Include the CoAP implementation +MODULES += os/net/app-layer/coap + +CONTIKI=../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/coap/coap-example-client.c b/examples/coap/coap-example-client/coap-example-client.c similarity index 70% rename from examples/coap/coap-example-client.c rename to examples/coap/coap-example-client/coap-example-client.c index 5ef8f4fcea4345f98e2f4f7811dee6dbaffc1307..1606d884a3e76e517714c7154c907c409d941580 100644 --- a/examples/coap/coap-example-client.c +++ b/examples/coap/coap-example-client/coap-example-client.c @@ -42,33 +42,26 @@ #include "contiki.h" #include "contiki-net.h" #include "coap-engine.h" -#include "dev/button-sensor.h" - -#define DEBUG 0 -#if DEBUG -#include <stdio.h> -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) +#include "coap-blocking-api.h" +#if PLATFORM_SUPPORTS_BUTTON_HAL +#include "dev/button-hal.h" #else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) +#include "dev/button-sensor.h" #endif -/* FIXME: This server address is hard-coded for Cooja and link-local for unconnected border router. */ -#define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7402, 0x0002, 0x0202) /* cooja2 */ -/* #define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xbbbb, 0, 0, 0, 0, 0, 0, 0x1) */ +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "App" +#define LOG_LEVEL LOG_LEVEL_APP -#define LOCAL_PORT UIP_HTONS(COAP_DEFAULT_PORT + 1) -#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) +/* FIXME: This server address is hard-coded for Cooja and link-local for unconnected border router. */ +#define SERVER_EP "coap://[fe80::212:7402:0002:0202]" #define TOGGLE_INTERVAL 10 PROCESS(er_example_client, "Erbium Example Client"); AUTOSTART_PROCESSES(&er_example_client); -uip_ipaddr_t server_ipaddr; static struct etimer et; /* Example URIs that can be queried. */ @@ -82,7 +75,7 @@ static int uri_switch = 0; /* This function is will be passed to COAP_BLOCKING_REQUEST() to handle responses. */ void -client_chunk_handler(void *response) +client_chunk_handler(coap_message_t *response) { const uint8_t *chunk; @@ -92,21 +85,24 @@ client_chunk_handler(void *response) } PROCESS_THREAD(er_example_client, ev, data) { + static coap_endpoint_t server_ep; PROCESS_BEGIN(); - static coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */ + static coap_message_t request[1]; /* This way the packet can be treated as pointer as usual. */ - SERVER_NODE(&server_ipaddr); + coap_endpoint_parse(SERVER_EP, strlen(SERVER_EP), &server_ep); /* receives all CoAP messages */ - coap_init_engine(); + coap_engine_init(); etimer_set(&et, TOGGLE_INTERVAL * CLOCK_SECOND); #if PLATFORM_HAS_BUTTON +#if !PLATFORM_SUPPORTS_BUTTON_HAL SENSORS_ACTIVATE(button_sensor); - printf("Press a button to request %s\n", service_urls[uri_switch]); #endif + printf("Press a button to request %s\n", service_urls[uri_switch]); +#endif /* PLATFORM_HAS_BUTTON */ while(1) { PROCESS_YIELD(); @@ -122,18 +118,21 @@ PROCESS_THREAD(er_example_client, ev, data) coap_set_payload(request, (uint8_t *)msg, sizeof(msg) - 1); - PRINT6ADDR(&server_ipaddr); - PRINTF(" : %u\n", UIP_HTONS(REMOTE_PORT)); + LOG_INFO_COAP_EP(&server_ep); + LOG_INFO_("\n"); - COAP_BLOCKING_REQUEST(&server_ipaddr, REMOTE_PORT, request, - client_chunk_handler); + COAP_BLOCKING_REQUEST(&server_ep, request, client_chunk_handler); printf("\n--Done--\n"); etimer_reset(&et); #if PLATFORM_HAS_BUTTON +#if PLATFORM_SUPPORTS_BUTTON_HAL + } else if(ev == button_hal_release_event) { +#else } else if(ev == sensors_event && data == &button_sensor) { +#endif /* send a request to notify the end of the process */ @@ -142,16 +141,16 @@ PROCESS_THREAD(er_example_client, ev, data) printf("--Requesting %s--\n", service_urls[uri_switch]); - PRINT6ADDR(&server_ipaddr); - PRINTF(" : %u\n", UIP_HTONS(REMOTE_PORT)); + LOG_INFO_COAP_EP(&server_ep); + LOG_INFO_("\n"); - COAP_BLOCKING_REQUEST(&server_ipaddr, REMOTE_PORT, request, + COAP_BLOCKING_REQUEST(&server_ep, request, client_chunk_handler); printf("\n--Done--\n"); uri_switch = (uri_switch + 1) % NUMBER_OF_URLS; -#endif +#endif /* PLATFORM_HAS_BUTTON */ } } diff --git a/examples/coap/coap-example-observe-client.c b/examples/coap/coap-example-client/coap-example-observe-client.c similarity index 84% rename from examples/coap/coap-example-observe-client.c rename to examples/coap/coap-example-client/coap-example-observe-client.c index 6d6b0c5cbf6354f0e1cba26e897a9575430f1681..914a21bddf32aae6e2bda124a1fca94c96095a59 100644 --- a/examples/coap/coap-example-observe-client.c +++ b/examples/coap/coap-example-client/coap-example-observe-client.c @@ -42,29 +42,17 @@ #include "contiki.h" #include "contiki-net.h" #include "coap-engine.h" -#include "dev/button-sensor.h" - -/*----------------------------------------------------------------------------*/ -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINTFLN(format, ...) printf(format "\n", ##__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:" \ - "%02x%02x:%02x%02x:%02x%02x:%02x%02x]", \ - ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], \ - ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], \ - ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], \ - ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], \ - ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], \ - ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], \ - ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], \ - ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) +#if PLATFORM_SUPPORTS_BUTTON_HAL +#include "dev/button-hal.h" #else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTFLN(...) +#include "dev/button-sensor.h" #endif +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "App" +#define LOG_LEVEL LOG_LEVEL_APP + /*----------------------------------------------------------------------------*/ /* FIXME: This server address is hard-coded for Cooja */ #define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, \ @@ -158,9 +146,12 @@ PROCESS_THREAD(er_example_observe_client, ev, data) /* init timer and button (if available) */ etimer_set(&et, TOGGLE_INTERVAL * CLOCK_SECOND); #if PLATFORM_HAS_BUTTON +#if !PLATFORM_SUPPORTS_BUTTON_HAL SENSORS_ACTIVATE(button_sensor); - printf("Press a button to start/stop observation of remote resource\n"); #endif + printf("Press a button to start/stop observation of remote resource\n"); +#endif /* PLATFORM_HAS_BUTTON */ + /* toggle observation every time the timer elapses or the button is pressed */ while(1) { PROCESS_YIELD(); @@ -170,11 +161,15 @@ PROCESS_THREAD(er_example_observe_client, ev, data) printf("\n--Done--\n"); etimer_reset(&et); #if PLATFORM_HAS_BUTTON +#if PLATFORM_SUPPORTS_BUTTON_HAL + } else if(ev == button_hal_release_event) { +#else } else if(ev == sensors_event && data == &button_sensor) { +#endif printf("--Toggle tutton--\n"); toggle_observation(); printf("\n--Done--\n"); -#endif +#endif /* PLATFORM_HAS_BUTTON */ } } PROCESS_END(); diff --git a/arch/cpu/msp430/mtarch.h b/examples/coap/coap-example-client/project-conf.h similarity index 78% rename from arch/cpu/msp430/mtarch.h rename to examples/coap/coap-example-client/project-conf.h index f321bd176894549c103348a744681b8dfa7124e1..7247ea08cdaa1198cf04981f443d040f9c5208a4 100644 --- a/arch/cpu/msp430/mtarch.h +++ b/examples/coap/coap-example-client/project-conf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Swedish Institute of Computer Science + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,24 +28,20 @@ * * This file is part of the Contiki operating system. */ -#ifndef MTARCH_H_ -#define MTARCH_H_ -#include "contiki.h" - -#ifndef MTARCH_STACKSIZE -#define MTARCH_STACKSIZE 128 -#endif /* MTARCH_STACKSIZE */ +/** + * \file + * Erbium (Er) example project configuration. + * \author + * Matthias Kovatsch <kovatsch@inf.ethz.ch> + */ -struct mtarch_thread { - unsigned short stack[MTARCH_STACKSIZE]; - unsigned short *sp; - void *data; - void (* function)(void *); -}; +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ -struct mt_thread; +#define LOG_LEVEL_APP LOG_LEVEL_DBG -int mtarch_stack_usage(struct mt_thread *t); +/* Enable client-side support for COAP observe */ +#define COAP_OBSERVE_CLIENT 1 -#endif /* MTARCH_H_ */ +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/coap/coap-example-server/Makefile b/examples/coap/coap-example-server/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..6d9e2db85ab36e2874128abda05db11428515f31 --- /dev/null +++ b/examples/coap/coap-example-server/Makefile @@ -0,0 +1,14 @@ +CONTIKI_PROJECT = coap-example-server +all: $(CONTIKI_PROJECT) + +# Do not try to build on Sky because of code size limitation +PLATFORMS_EXCLUDE = sky + +# Include the CoAP implementation +MODULES += os/net/app-layer/coap + +# Include CoAP resources +MODULES_REL += ./resources + +CONTIKI=../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/coap/coap-example-server.c b/examples/coap/coap-example-server/coap-example-server.c similarity index 54% rename from examples/coap/coap-example-server.c rename to examples/coap/coap-example-server/coap-example-server.c index 79c25d501a923c25ac88efa5726fe2973e91df27..375fc4bd9c9b3790d2d59b344a782d20c14bd0ae 100644 --- a/examples/coap/coap-example-server.c +++ b/examples/coap/coap-example-server/coap-example-server.c @@ -31,7 +31,7 @@ /** * \file - * Erbium (Er) REST Engine example. + * Erbium (Er) CoAP Engine example. * \author * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ @@ -40,30 +40,23 @@ #include <stdlib.h> #include <string.h> #include "contiki.h" -#include "contiki-net.h" -#include "rest-engine.h" +#include "coap-engine.h" -#if PLATFORM_HAS_BUTTON -#include "dev/button-sensor.h" -#endif - -#define DEBUG 0 -#if DEBUG -#include <stdio.h> -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) +#if PLATFORM_SUPPORTS_BUTTON_HAL +#include "dev/button-hal.h" #else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) +#include "dev/button-sensor.h" #endif +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "App" +#define LOG_LEVEL LOG_LEVEL_APP /* * Resources to be activated need to be imported through the extern keyword. * The build system automatically compiles the resources in the corresponding sub-directory. */ -extern resource_t +extern coap_resource_t res_hello, res_mirror, res_chunks, @@ -73,31 +66,20 @@ extern resource_t res_sub, res_b1_sep_b2; #if PLATFORM_HAS_LEDS -extern resource_t res_leds, res_toggle; +extern coap_resource_t res_leds, res_toggle; #endif #if PLATFORM_HAS_LIGHT #include "dev/light-sensor.h" -extern resource_t res_light; +extern coap_resource_t res_light; #endif #if PLATFORM_HAS_BATTERY #include "dev/battery-sensor.h" -extern resource_t res_battery; +extern coap_resource_t res_battery; #endif #if PLATFORM_HAS_TEMPERATURE #include "dev/temperature-sensor.h" -extern resource_t res_temperature; +extern coap_resource_t res_temperature; #endif -/* -extern resource_t res_battery; -#endif -#if PLATFORM_HAS_RADIO -extern resource_t res_radio; -#endif -#if PLATFORM_HAS_SHT11 -#include "dev/sht11/sht11-sensor.h" -extern resource_t res_sht11; -#endif -*/ PROCESS(er_example_server, "Erbium Example Server"); AUTOSTART_PROCESSES(&er_example_server); @@ -108,68 +90,53 @@ PROCESS_THREAD(er_example_server, ev, data) PROCESS_PAUSE(); - PRINTF("Starting Erbium Example Server\n"); - -#ifdef RF_CHANNEL - PRINTF("RF channel: %u\n", RF_CHANNEL); -#endif -#ifdef IEEE802154_PANID - PRINTF("PAN ID: 0x%04X\n", IEEE802154_PANID); -#endif - - PRINTF("uIP buffer: %u\n", UIP_BUFSIZE); - PRINTF("LL header: %u\n", UIP_LLH_LEN); - PRINTF("IP+UDP header: %u\n", UIP_IPUDPH_LEN); - PRINTF("REST max chunk: %u\n", REST_MAX_CHUNK_SIZE); + LOG_INFO("Starting Erbium Example Server\n"); /* Initialize the REST engine. */ - rest_init_engine(); + coap_engine_init(); /* * Bind the resources to their Uri-Path. * WARNING: Activating twice only means alternate path, not two instances! * All static variables are the same for each URI path. */ - rest_activate_resource(&res_hello, "test/hello"); -/* rest_activate_resource(&res_mirror, "debug/mirror"); */ -/* rest_activate_resource(&res_chunks, "test/chunks"); */ -/* rest_activate_resource(&res_separate, "test/separate"); */ - rest_activate_resource(&res_push, "test/push"); -/* rest_activate_resource(&res_event, "sensors/button"); */ -/* rest_activate_resource(&res_sub, "test/sub"); */ -/* rest_activate_resource(&res_b1_sep_b2, "test/b1sepb2"); */ + coap_activate_resource(&res_hello, "test/hello"); + coap_activate_resource(&res_mirror, "debug/mirror"); + coap_activate_resource(&res_chunks, "test/chunks"); + coap_activate_resource(&res_separate, "test/separate"); + coap_activate_resource(&res_push, "test/push"); +#if PLATFORM_HAS_BUTTON + coap_activate_resource(&res_event, "sensors/button"); +#endif /* PLATFORM_HAS_BUTTON */ + coap_activate_resource(&res_sub, "test/sub"); + coap_activate_resource(&res_b1_sep_b2, "test/b1sepb2"); #if PLATFORM_HAS_LEDS -/* rest_activate_resource(&res_leds, "actuators/leds"); */ - rest_activate_resource(&res_toggle, "actuators/toggle"); +/* coap_activate_resource(&res_leds, "actuators/leds"); */ + coap_activate_resource(&res_toggle, "actuators/toggle"); #endif #if PLATFORM_HAS_LIGHT - rest_activate_resource(&res_light, "sensors/light"); - SENSORS_ACTIVATE(light_sensor); + coap_activate_resource(&res_light, "sensors/light"); + SENSORS_ACTIVATE(light_sensor); #endif #if PLATFORM_HAS_BATTERY - rest_activate_resource(&res_battery, "sensors/battery"); - SENSORS_ACTIVATE(battery_sensor); + coap_activate_resource(&res_battery, "sensors/battery"); + SENSORS_ACTIVATE(battery_sensor); #endif #if PLATFORM_HAS_TEMPERATURE - rest_activate_resource(&res_temperature, "sensors/temperature"); - SENSORS_ACTIVATE(temperature_sensor); + coap_activate_resource(&res_temperature, "sensors/temperature"); + SENSORS_ACTIVATE(temperature_sensor); #endif -/* -#if PLATFORM_HAS_RADIO - rest_activate_resource(&res_radio, "sensors/radio"); -#endif -#if PLATFORM_HAS_SHT11 - rest_activate_resource(&res_sht11, "sensors/sht11"); - SENSORS_ACTIVATE(sht11_sensor); -#endif -*/ /* Define application-specific events here. */ while(1) { PROCESS_WAIT_EVENT(); #if PLATFORM_HAS_BUTTON +#if PLATFORM_SUPPORTS_BUTTON_HAL + if(ev == button_hal_release_event) { +#else if(ev == sensors_event && data == &button_sensor) { - PRINTF("*******BUTTON*******\n"); +#endif + LOG_DBG("*******BUTTON*******\n"); /* Call the event_handler for this application-specific event. */ res_event.trigger(); diff --git a/examples/coap/coap-example-server/project-conf.h b/examples/coap/coap-example-server/project-conf.h new file mode 100644 index 0000000000000000000000000000000000000000..eeec89082ab0a9c5372542e8e73b3dc199165ec9 --- /dev/null +++ b/examples/coap/coap-example-server/project-conf.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Erbium (Er) example project configuration. + * \author + * Matthias Kovatsch <kovatsch@inf.ethz.ch> + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#define LOG_LEVEL_APP LOG_LEVEL_DBG + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/coap/resources/res-b1-sep-b2.c b/examples/coap/coap-example-server/resources/res-b1-sep-b2.c similarity index 88% rename from examples/coap/resources/res-b1-sep-b2.c rename to examples/coap/coap-example-server/resources/res-b1-sep-b2.c index 26b6b8606a6598ea892010e4171d493f07f0d247..0fa76726f608a54fa7b3a60cb9b1ef7a5e916b2d 100644 --- a/examples/coap/resources/res-b1-sep-b2.c +++ b/examples/coap/coap-example-server/resources/res-b1-sep-b2.c @@ -36,13 +36,14 @@ * Lars Schmertmann <SmallLars@t-online.de> */ +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap-block1.h" #include "coap-separate.h" #include "coap-transactions.h" -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); SEPARATE_RESOURCE(res_b1_sep_b2, "title=\"Block1 + Separate + Block2 demo\"", NULL, res_post_handler, NULL, NULL, NULL); #define MAX_DATA_LEN 256 @@ -52,7 +53,7 @@ static size_t big_msg_len = 0; static coap_separate_t request_metadata; static void -res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* Example allows only one request on time. There are no checks for multiply access !!! */ if(*offset == 0) { @@ -75,8 +76,8 @@ res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t prefer /* Send first block */ coap_transaction_t *transaction = NULL; - if((transaction = coap_new_transaction(request_metadata.mid, &request_metadata.addr, request_metadata.port))) { - coap_packet_t resp[1]; /* This way the packet can be treated as pointer as usual. */ + if((transaction = coap_new_transaction(request_metadata.mid, &request_metadata.endpoint))) { + coap_message_t resp[1]; /* This way the message can be treated as pointer as usual. */ /* Restore the request information for the response. */ coap_separate_resume(resp, &request_metadata, CONTENT_2_05); @@ -88,7 +89,7 @@ res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t prefer } /* Warning: No check for serialization error. */ - transaction->packet_len = coap_serialize_message(resp, transaction->packet); + transaction->message_len = coap_serialize_message(resp, transaction->message); coap_send_transaction(transaction); } } else { diff --git a/examples/coap/resources/res-battery.c b/examples/coap/coap-example-server/resources/res-battery.c similarity index 70% rename from examples/coap/resources/res-battery.c rename to examples/coap/coap-example-server/resources/res-battery.c index b8252359404bd8880e1c0b58bce95b7c196c7666..b4c7623b3fd2578ff41a604d81587e08850a4e88 100644 --- a/examples/coap/resources/res-battery.c +++ b/examples/coap/coap-example-server/resources/res-battery.c @@ -41,10 +41,11 @@ #if PLATFORM_HAS_BATTERY #include <string.h> -#include "rest-engine.h" +#include <stdio.h> +#include "coap-engine.h" #include "dev/battery-sensor.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple getter example. Returns the reading from light sensor with a simple etag */ RESOURCE(res_battery, @@ -55,27 +56,27 @@ RESOURCE(res_battery, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int battery = battery_sensor.value(0); unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", battery); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%d", battery); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'battery':%d}", battery); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'battery':%d}", battery); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain and application/json"; - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_payload(response, msg, strlen(msg)); } } #endif /* PLATFORM_HAS_BATTERY */ diff --git a/examples/coap/resources/res-chunks.c b/examples/coap/coap-example-server/resources/res-chunks.c similarity index 86% rename from examples/coap/resources/res-chunks.c rename to examples/coap/coap-example-server/resources/res-chunks.c index 13de706c85dfc54575b44c0637c6d93f1a37fb8f..39555d091d7facc7b556c4ee58d6868a2a967006 100644 --- a/examples/coap/resources/res-chunks.c +++ b/examples/coap/coap-example-server/resources/res-chunks.c @@ -36,13 +36,14 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* - * For data larger than REST_MAX_CHUNK_SIZE (e.g., when stored in flash) resources must be aware of the buffer limitation + * For data larger than COAP_MAX_CHUNK_SIZE (e.g., when stored in flash) resources must be aware of the buffer limitation * and split their responses by themselves. To transfer the complete resource through a TCP stream or CoAP's blockwise transfer, * the byte offset where to continue is provided to the handler as int32_t pointer. * These chunk-wise resources must set the offset value to its new position or -1 of the end is reached. @@ -58,17 +59,17 @@ RESOURCE(res_chunks, #define CHUNKS_TOTAL 2050 static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int32_t strpos = 0; /* Check the offset for boundaries of the resource data. */ if(*offset >= CHUNKS_TOTAL) { - REST.set_response_status(response, REST.status.BAD_OPTION); + coap_set_status_code(response, BAD_OPTION_4_02); /* A block error message should not exceed the minimum block size (16). */ const char *error_msg = "BlockOutOfScope"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } @@ -85,7 +86,7 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr if(*offset + (int32_t)strpos > CHUNKS_TOTAL) { strpos = CHUNKS_TOTAL - *offset; } - REST.set_response_payload(response, buffer, strpos); + coap_set_payload(response, buffer, strpos); /* IMPORTANT for chunk-wise resources: Signal chunk awareness to REST engine. */ *offset += strpos; diff --git a/examples/coap/resources/res-event.c b/examples/coap/coap-example-server/resources/res-event.c similarity index 69% rename from examples/coap/resources/res-event.c rename to examples/coap/coap-example-server/resources/res-event.c index 35ff1f8ebd7bfe507032d5cd3acbd1cbfb3d0a81..f8f754afae0f71baf65c41577fcedd21beeaa7a0 100644 --- a/examples/coap/resources/res-event.c +++ b/examples/coap/coap-example-server/resources/res-event.c @@ -36,23 +36,17 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -#define DEBUG 0 -#if DEBUG -#include <stdio.h> -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "App" +#define LOG_LEVEL LOG_LEVEL_APP -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_event_handler(void); /* @@ -74,10 +68,10 @@ EVENT_RESOURCE(res_event, static int32_t event_counter = 0; static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, buffer, snprintf((char *)buffer, preferred_size, "EVENT %lu", (unsigned long) event_counter)); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, buffer, snprintf((char *)buffer, preferred_size, "EVENT %lu", (unsigned long) event_counter)); /* A post_handler that handles subscriptions/observing will be called for periodic resources by the framework. */ } @@ -93,9 +87,9 @@ res_event_handler(void) /* Usually a condition is defined under with subscribers are notified, e.g., event was above a threshold. */ if(1) { - PRINTF("TICK %u for /%s\n", event_counter, res_event.url); + LOG_DBG("TICK %u for /%s\n", (unsigned)event_counter, res_event.url); /* Notify the registered observers which will trigger the res_get_handler to create the response. */ - REST.notify_subscribers(&res_event); + coap_notify_observers(&res_event); } } diff --git a/examples/coap/resources/res-hello.c b/examples/coap/coap-example-server/resources/res-hello.c similarity index 83% rename from examples/coap/resources/res-hello.c rename to examples/coap/coap-example-server/resources/res-hello.c index 9208f8b740ea86afc4326b2ca6a0d8d073be9f3f..914bc28d6a4ac20d96a5cb762345857e6f87ae5b 100644 --- a/examples/coap/resources/res-hello.c +++ b/examples/coap/coap-example-server/resources/res-hello.c @@ -38,9 +38,9 @@ #include <stdlib.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* * A handler function named [resource name]_handler must be implemented for each RESOURCE. @@ -56,7 +56,7 @@ RESOURCE(res_hello, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *len = NULL; /* Some data that has the length up to REST_MAX_CHUNK_SIZE. For more, see the chunk resource. */ @@ -64,7 +64,7 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr int length = 12; /* |<-------->| */ /* The query string can be retrieved by rest_get_query() or parsed for its key-value pairs. */ - if(REST.get_query_variable(request, "len", &len)) { + if(coap_get_query_variable(request, "len", &len)) { length = atoi(len); if(length < 0) { length = 0; @@ -75,7 +75,9 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr memcpy(buffer, message, length); } else { memcpy(buffer, message, length); - } REST.set_header_content_type(response, REST.type.TEXT_PLAIN); /* text/plain is the default, hence this option could be omitted. */ - REST.set_header_etag(response, (uint8_t *)&length, 1); - REST.set_response_payload(response, buffer, length); + } + + coap_set_header_content_format(response, TEXT_PLAIN); /* text/plain is the default, hence this option could be omitted. */ + coap_set_header_etag(response, (uint8_t *)&length, 1); + coap_set_payload(response, buffer, length); } diff --git a/examples/coap/resources/res-leds.c b/examples/coap/coap-example-server/resources/res-leds.c similarity index 63% rename from examples/coap/resources/res-leds.c rename to examples/coap/coap-example-server/resources/res-leds.c index 5fbcf6c776ab913b93a0dd24b294f9364f668b38..72dbc8b41f05eafb122e70753bfda8ecce6b912a 100644 --- a/examples/coap/resources/res-leds.c +++ b/examples/coap/coap-example-server/resources/res-leds.c @@ -37,28 +37,21 @@ */ #include "contiki.h" - -#if PLATFORM_HAS_LEDS +#include "coap-engine.h" +#include "dev/leds.h" #include <string.h> -#include "rest-engine.h" -#include "dev/leds.h" -#define DEBUG 0 -#if DEBUG -#include <stdio.h> -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +#if PLATFORM_HAS_LEDS || LEDS_COUNT + +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "App" +#define LOG_LEVEL LOG_LEVEL_APP -static void res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -/*A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated*/ +/* A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated */ RESOURCE(res_leds, "title=\"LEDs: ?color=r|g|b, POST/PUT mode=on|off\";rt=\"Control\"", NULL, @@ -67,7 +60,7 @@ RESOURCE(res_leds, NULL); static void -res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { size_t len = 0; const char *color = NULL; @@ -75,8 +68,8 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t pr uint8_t led = 0; int success = 1; - if((len = REST.get_query_variable(request, "color", &color))) { - PRINTF("color %.*s\n", len, color); + if((len = coap_get_query_variable(request, "color", &color))) { + LOG_DBG("color %.*s\n", (int)len, color); if(strncmp(color, "r", len) == 0) { led = LEDS_RED; @@ -89,8 +82,8 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t pr } } else { success = 0; - } if(success && (len = REST.get_post_variable(request, "mode", &mode))) { - PRINTF("mode %s\n", mode); + } if(success && (len = coap_get_post_variable(request, "mode", &mode))) { + LOG_DBG("mode %s\n", mode); if(strncmp(mode, "on", len) == 0) { leds_on(led); @@ -102,7 +95,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t pr } else { success = 0; } if(!success) { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); } } #endif /* PLATFORM_HAS_LEDS */ diff --git a/examples/coap/resources/res-light.c b/examples/coap/coap-example-server/resources/res-light.c similarity index 68% rename from examples/coap/resources/res-light.c rename to examples/coap/coap-example-server/resources/res-light.c index 226d814bbe42985d4423368890e63975bc08f398..3384b2e5fb349a453004a89e8f069777d306c24a 100644 --- a/examples/coap/resources/res-light.c +++ b/examples/coap/coap-example-server/resources/res-light.c @@ -40,11 +40,12 @@ #if PLATFORM_HAS_LIGHT +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/light-sensor.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple getter example. Returns the reading from light sensor with a simple etag */ RESOURCE(res_light, @@ -55,33 +56,33 @@ RESOURCE(res_light, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { uint16_t light_photosynthetic = light_sensor.value(LIGHT_SENSOR_PHOTOSYNTHETIC); uint16_t light_solar = light_sensor.value(LIGHT_SENSOR_TOTAL_SOLAR); unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%u;%u", light_photosynthetic, light_solar); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%u;%u", light_photosynthetic, light_solar); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "<light photosynthetic=\"%u\" solar=\"%u\"/>", light_photosynthetic, light_solar); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "<light photosynthetic=\"%u\" solar=\"%u\"/>", light_photosynthetic, light_solar); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'light':{'photosynthetic':%u,'solar':%u}}", light_photosynthetic, light_solar); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'light':{'photosynthetic':%u,'solar':%u}}", light_photosynthetic, light_solar); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain, application/xml, and application/json"; - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_payload(response, msg, strlen(msg)); } } #endif /* PLATFORM_HAS_LIGHT */ diff --git a/examples/coap/resources/res-mirror.c b/examples/coap/coap-example-server/resources/res-mirror.c similarity index 75% rename from examples/coap/resources/res-mirror.c rename to examples/coap/coap-example-server/resources/res-mirror.c index 15b7c3b80cd78394b4881404e1485a3d86a16424..619ed08a737cc39ad2a4359e466cb185a71e5476 100644 --- a/examples/coap/resources/res-mirror.c +++ b/examples/coap/coap-example-server/resources/res-mirror.c @@ -36,23 +36,17 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -#define DEBUG 0 -#if DEBUG -#include <stdio.h> -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "App" +#define LOG_LEVEL LOG_LEVEL_APP -static void res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_any_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* This resource mirrors the incoming request. It shows how to access the options and how to set them for the response. */ RESOURCE(res_mirror, @@ -63,7 +57,7 @@ RESOURCE(res_mirror, res_any_handler); static void -res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_any_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* The ETag and Token is copied to the header. */ uint8_t opaque[] = { 0x0A, 0xBC, 0xDE }; @@ -89,28 +83,28 @@ res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr /* snprintf() counts the terminating '\0' to the size parameter. * The additional byte is taken care of by allocating REST_MAX_CHUNK_SIZE+1 bytes in the REST framework. * Add +1 to fill the complete buffer, as the payload does not need a terminating '\0'. */ - if(REST.get_header_content_type(request, &content_format)) { + if(coap_get_header_content_format(request, &content_format)) { strpos += snprintf((char *)buffer, REST_MAX_CHUNK_SIZE + 1, "CF %u\n", content_format); } - if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_header_accept(request, &content_format))) { + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_accept(request, &content_format))) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "Ac %u\n", content_format); /* Some getters such as for ETag or Location are omitted, as these options should not appear in a request. * Max-Age might appear in HTTP requests or used for special purposes in CoAP. */ } - if(strpos <= REST_MAX_CHUNK_SIZE && REST.get_header_max_age(request, &longint)) { + if(strpos <= REST_MAX_CHUNK_SIZE && coap_get_header_max_age(request, &longint)) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "MA %lu\n", (unsigned long) longint); /* For HTTP this is the Length option, for CoAP it is the Size option. */ } - if(strpos <= REST_MAX_CHUNK_SIZE && REST.get_header_length(request, &longint)) { + if(strpos <= REST_MAX_CHUNK_SIZE && coap_get_header_size1(request, &longint)) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "SZ %lu\n", (unsigned long) longint); } - if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_header_host(request, &str))) { + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_uri_host(request, &str))) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "UH %.*s\n", len, str); } - if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_url(request, &str))) { + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_uri_path(request, &str))) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "UP %.*s\n", len, str); } - if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_query(request, &str))) { + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_uri_query(request, &str))) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "UQ %.*s\n", len, str); /* Undefined request options for debugging: actions not required for normal RESTful Web service. */ } @@ -121,7 +115,7 @@ res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "LQ %.*s\n", len, str); /* CoAP-specific example: actions not required for normal RESTful Web service. */ } - coap_packet_t *const coap_pkt = (coap_packet_t *)request; + coap_message_t *const coap_pkt = (coap_message_t *)request; if(strpos <= REST_MAX_CHUNK_SIZE && coap_pkt->token_len > 0) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "To 0x"); @@ -132,10 +126,10 @@ res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "\n"); } - if(strpos <= REST_MAX_CHUNK_SIZE && IS_OPTION(coap_pkt, COAP_OPTION_OBSERVE)) { + if(strpos <= REST_MAX_CHUNK_SIZE && coap_is_option(coap_pkt, COAP_OPTION_OBSERVE)) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "Ob %lu\n", (unsigned long) coap_pkt->observe); } - if(strpos <= REST_MAX_CHUNK_SIZE && IS_OPTION(coap_pkt, COAP_OPTION_ETAG)) { + if(strpos <= REST_MAX_CHUNK_SIZE && coap_is_option(coap_pkt, COAP_OPTION_ETAG)) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "ET 0x"); int index = 0; for(index = 0; index < coap_pkt->etag_len; ++index) { @@ -149,22 +143,22 @@ res_any_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr if(strpos <= REST_MAX_CHUNK_SIZE && coap_get_header_block1(request, &block_num, &block_more, &block_size, NULL)) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "B1 %lu%s (%u)\n", (unsigned long) block_num, block_more ? "+" : "", block_size); } - if(strpos <= REST_MAX_CHUNK_SIZE && (len = REST.get_request_payload(request, &bytes))) { + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_payload(request, &bytes))) { strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "%.*s", len, bytes); } if(strpos >= REST_MAX_CHUNK_SIZE) { buffer[REST_MAX_CHUNK_SIZE - 1] = 0xBB; /* '»' to indicate truncation */ } - REST.set_response_payload(response, buffer, strpos); + coap_set_payload(response, buffer, strpos); - PRINTF("/mirror options received: %s\n", buffer); + LOG_DBG("/mirror options received: %s\n", buffer); /* Set dummy header options for response. Like getters, some setters are not implemented for HTTP and have no effect. */ - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_header_max_age(response, 17); /* For HTTP, browsers will not re-request the page for 17 seconds. */ - REST.set_header_etag(response, opaque, 2); - REST.set_header_location(response, location); /* Initial slash is omitted by framework */ - REST.set_header_length(response, strpos); /* For HTTP, browsers will not re-request the page for 10 seconds. CoAP action depends on the client. */ + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_header_max_age(response, 17); /* For HTTP, browsers will not re-request the page for 17 seconds. */ + coap_set_header_etag(response, opaque, 2); + coap_set_header_location_path(response, location); /* Initial slash is omitted by framework */ + coap_set_header_size1(response, strpos); /* For HTTP, browsers will not re-request the page for 10 s. CoAP action depends on the client. */ /* CoAP-specific example: actions not required for normal RESTful Web service. */ coap_set_header_uri_host(response, "tiki"); diff --git a/examples/coap/resources/res-push.c b/examples/coap/coap-example-server/resources/res-push.c similarity index 81% rename from examples/coap/resources/res-push.c rename to examples/coap/coap-example-server/resources/res-push.c index 120e2ffef6f92b023ea26abf1e55507bfe081487..ffc8c9c0786c2c583de2d3fa52413a257225d2e8 100644 --- a/examples/coap/resources/res-push.c +++ b/examples/coap/coap-example-server/resources/res-push.c @@ -36,11 +36,12 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_periodic_handler(void); PERIODIC_RESOURCE(res_push, @@ -58,18 +59,18 @@ PERIODIC_RESOURCE(res_push, static int32_t event_counter = 0; static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* * For minimal complexity, request query and options should be ignored for GET on observable resources. - * Otherwise the requests must be stored with the observer list and passed by REST.notify_subscribers(). + * Otherwise the requests must be stored with the observer list and passed by coap_notify_subscribers(). * This would be a TODO in the corresponding files in contiki/apps/erbium/! */ - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_header_max_age(response, res_push.periodic->period / CLOCK_SECOND); - REST.set_response_payload(response, buffer, snprintf((char *)buffer, preferred_size, "VERY LONG EVENT %lu", (unsigned long) event_counter)); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_header_max_age(response, res_push.periodic->period / CLOCK_SECOND); + coap_set_payload(response, buffer, snprintf((char *)buffer, preferred_size, "VERY LONG EVENT %lu", (unsigned long) event_counter)); - /* The REST.subscription_handler() will be called for observable resources by the REST framework. */ + /* The coap_subscription_handler() will be called for observable resources by the REST framework. */ } /* * Additionally, a handler function named [resource name]_handler must be implemented for each PERIODIC_RESOURCE. @@ -84,6 +85,6 @@ res_periodic_handler() /* Usually a condition is defined under with subscribers are notified, e.g., large enough delta in sensor reading. */ if(1) { /* Notify the registered observers which will trigger the res_get_handler to create the response. */ - REST.notify_subscribers(&res_push); + coap_notify_observers(&res_push); } } diff --git a/examples/coap/resources/res-radio.c b/examples/coap/coap-example-server/resources/res-radio.c similarity index 70% rename from examples/coap/resources/res-radio.c rename to examples/coap/coap-example-server/resources/res-radio.c index b33bf703a7f9e59cad08527120d2e6467c101376..c23436bb68ef768da47efa2caa767e1d536f2d32 100644 --- a/examples/coap/resources/res-radio.c +++ b/examples/coap/coap-example-server/resources/res-radio.c @@ -39,12 +39,12 @@ #include "contiki.h" #if PLATFORM_HAS_RADIO - +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "net/netstack.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple getter example. Returns the reading of the rssi/lqi from radio sensor */ RESOURCE(res_radio, @@ -55,7 +55,7 @@ RESOURCE(res_radio, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { size_t len = 0; const char *p = NULL; @@ -64,9 +64,9 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr int success = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if((len = REST.get_query_variable(request, "p", &p))) { + if((len = coap_get_query_variable(request, "p", &p))) { if(strncmp(p, "rssi", len) == 0) { if(NETSTACK_RADIO.get_value(RADIO_PARAM_RSSI, &value) == RADIO_RESULT_OK) { @@ -77,23 +77,23 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr } if(success) { - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", rssi); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%d", rssi); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'rssi':%d}", rssi); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'rssi':%d}", rssi); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain and application/json"; - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_payload(response, msg, strlen(msg)); } } else { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); } } #endif /* PLATFORM_HAS_RADIO */ diff --git a/examples/coap/resources/res-separate.c b/examples/coap/coap-example-server/resources/res-separate.c similarity index 88% rename from examples/coap/resources/res-separate.c rename to examples/coap/coap-example-server/resources/res-separate.c index fb402d2b9b240a81168442e93e1d84fa9045dbd2..6b98345bb4cf2994b67815f731fcf3a34e5f9090 100644 --- a/examples/coap/resources/res-separate.c +++ b/examples/coap/coap-example-server/resources/res-separate.c @@ -37,11 +37,12 @@ */ #include <string.h> -#include "rest-engine.h" +#include <stdio.h> +#include "coap-engine.h" #include "coap-separate.h" #include "coap-transactions.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_resume_handler(void); SEPARATE_RESOURCE(res_separate, @@ -68,7 +69,7 @@ static uint8_t separate_active = 0; static application_separate_store_t separate_store[COAP_MAX_OPEN_SEPARATE]; static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* * Example allows only one open separate response. @@ -96,11 +97,11 @@ res_resume_handler() { if(separate_active) { coap_transaction_t *transaction = NULL; - if((transaction = coap_new_transaction(separate_store->request_metadata.mid, &separate_store->request_metadata.addr, separate_store->request_metadata.port))) { - coap_packet_t response[1]; /* This way the packet can be treated as pointer as usual. */ + if((transaction = coap_new_transaction(separate_store->request_metadata.mid, &separate_store->request_metadata.endpoint))) { + coap_message_t response[1]; /* This way the message can be treated as pointer as usual. */ /* Restore the request information for the response. */ - coap_separate_resume(response, &separate_store->request_metadata, REST.status.OK); + coap_separate_resume(response, &separate_store->request_metadata, CONTENT_2_05); coap_set_payload(response, separate_store->buffer, strlen(separate_store->buffer)); @@ -111,7 +112,7 @@ res_resume_handler() coap_set_header_block2(response, separate_store->request_metadata.block2_num, 0, separate_store->request_metadata.block2_size); /* Warning: No check for serialization error. */ - transaction->packet_len = coap_serialize_message(response, transaction->packet); + transaction->message_len = coap_serialize_message(response, transaction->message); coap_send_transaction(transaction); /* The engine will clear the transaction (right after send for NON, after acked for CON). */ diff --git a/examples/coap/resources/res-sht11.c b/examples/coap/coap-example-server/resources/res-sht11.c similarity index 70% rename from examples/coap/resources/res-sht11.c rename to examples/coap/coap-example-server/resources/res-sht11.c index 56ed86c010421180fe1626661b275e2a2afcebdc..4dcf30e7005ce8c5192eb27ab549ce16cd557c9c 100644 --- a/examples/coap/resources/res-sht11.c +++ b/examples/coap/coap-example-server/resources/res-sht11.c @@ -43,11 +43,12 @@ #if PLATFORM_HAS_SHT11 +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/sht11/sht11-sensor.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* Get Method Example. Returns the reading from temperature and humidity sensors. */ RESOURCE(res_sht11, @@ -58,7 +59,7 @@ RESOURCE(res_sht11, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* Temperature in Celsius (t in 14 bits resolution at 3 Volts) * T = -39.60 + 0.01*t @@ -70,27 +71,27 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr uint16_t rh = sht11_sensor.value(SHT11_SENSOR_HUMIDITY); unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%u;%u", temperature, rh); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%u;%u", temperature, rh); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "<Temperature =\"%u\" Humidity=\"%u\"/>", temperature, rh); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "<Temperature =\"%u\" Humidity=\"%u\"/>", temperature, rh); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'Sht11':{'Temperature':%u,'Humidity':%u}}", temperature, rh); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'Sht11':{'Temperature':%u,'Humidity':%u}}", temperature, rh); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain, application/xml, and application/json"; - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_payload(response, msg, strlen(msg)); } } #endif /* PLATFORM_HAS_SHT11 */ diff --git a/examples/coap/resources/res-sub.c b/examples/coap/coap-example-server/resources/res-sub.c similarity index 76% rename from examples/coap/resources/res-sub.c rename to examples/coap/coap-example-server/resources/res-sub.c index 1d6f17aeb23c19fbba17f476c4c907b75616e2bb..88bc6a584cbcb1c865c066b658661730efee0bed 100644 --- a/examples/coap/resources/res-sub.c +++ b/examples/coap/coap-example-server/resources/res-sub.c @@ -36,14 +36,15 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* * Example for a resource that also handles all its sub-resources. - * Use REST.get_url() to multiplex the handling of the request depending on the Uri-Path. + * Use coap_get_url() to multiplex the handling of the request depending on the Uri-Path. */ PARENT_RESOURCE(res_sub, "title=\"Sub-resource demo\"", @@ -53,17 +54,17 @@ PARENT_RESOURCE(res_sub, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + coap_set_header_content_format(response, TEXT_PLAIN); const char *uri_path = NULL; - int len = REST.get_url(request, &uri_path); + int len = coap_get_header_uri_path(request, &uri_path); int base_len = strlen(res_sub.url); if(len == base_len) { - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "Request any sub-resource of /%s", res_sub.url); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "Request any sub-resource of /%s", res_sub.url); } else { - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, ".%.*s", len - base_len, uri_path + base_len); - } REST.set_response_payload(response, buffer, strlen((char *)buffer)); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, ".%.*s", len - base_len, uri_path + base_len); + } coap_set_payload(response, buffer, strlen((char *)buffer)); } diff --git a/examples/coap/resources/res-temperature.c b/examples/coap/coap-example-server/resources/res-temperature.c similarity index 73% rename from examples/coap/resources/res-temperature.c rename to examples/coap/coap-example-server/resources/res-temperature.c index c8bce8ba814367b4eed55fb29a6b58ffd9f50efc..ac34dbe33cdd90b80254951352767ab218443dd6 100644 --- a/examples/coap/resources/res-temperature.c +++ b/examples/coap/coap-example-server/resources/res-temperature.c @@ -44,11 +44,12 @@ #include <limits.h> #include <stdlib.h> +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/temperature-sensor.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_periodic_handler(void); #define MAX_AGE 60 @@ -69,43 +70,43 @@ PERIODIC_RESOURCE(res_temperature, res_periodic_handler); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* * For minimal complexity, request query and options should be ignored for GET on observable resources. - * Otherwise the requests must be stored with the observer list and passed by REST.notify_subscribers(). + * Otherwise the requests must be stored with the observer list and passed by coap_notify_observers(). * This would be a TODO in the corresponding files in contiki/apps/erbium/! */ int temperature = temperature_sensor.value(0); unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", temperature); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%d", temperature); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'temperature':%d}", temperature); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{'temperature':%d}", temperature); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain and application/json"; - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_payload(response, msg, strlen(msg)); } - REST.set_header_max_age(response, MAX_AGE); + coap_set_header_max_age(response, MAX_AGE); - /* The REST.subscription_handler() will be called for observable resources by the REST framework. */ + /* The coap_subscription_handler() will be called for observable resources by the coap_framework. */ } /* * Additionally, a handler function named [resource name]_handler must be implemented for each PERIODIC_RESOURCE. - * It will be called by the REST manager process with the defined period. + * It will be called by the coap_manager process with the defined period. */ static void res_periodic_handler() @@ -119,7 +120,7 @@ res_periodic_handler() interval_counter = 0; temperature_old = temperature; /* Notify the registered observers which will trigger the res_get_handler to create the response. */ - REST.notify_subscribers(&res_temperature); + coap_notify_observers(&res_temperature); } } #endif /* PLATFORM_HAS_TEMPERATURE */ diff --git a/examples/coap/resources/res-toggle.c b/examples/coap/coap-example-server/resources/res-toggle.c similarity index 86% rename from examples/coap/resources/res-toggle.c rename to examples/coap/coap-example-server/resources/res-toggle.c index d8a77330670ade8ed72a81eab3fdb5b6c5007ee6..b90ac77c7ccfa47a4e817c5307e9b6657033e8b9 100644 --- a/examples/coap/resources/res-toggle.c +++ b/examples/coap/coap-example-server/resources/res-toggle.c @@ -37,15 +37,14 @@ */ #include "contiki.h" - -#if PLATFORM_HAS_LEDS +#include "coap-engine.h" +#include "dev/leds.h" #include <string.h> -#include "contiki.h" -#include "rest-engine.h" -#include "dev/leds.h" -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +#if PLATFORM_HAS_LEDS || LEDS_COUNT + +static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple actuator example. Toggles the red led */ RESOURCE(res_toggle, @@ -56,7 +55,7 @@ RESOURCE(res_toggle, NULL); static void -res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_RED); } diff --git a/examples/coap/coap-plugtest-server/Makefile b/examples/coap/coap-plugtest-server/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..ee3bc511b7ee3f9413e572fa338cddf7d73fbfb3 --- /dev/null +++ b/examples/coap/coap-plugtest-server/Makefile @@ -0,0 +1,14 @@ +CONTIKI_PROJECT = coap-plugtest-server +all: $(CONTIKI_PROJECT) + +# Only intended for native +PLATFORMS_ONLY = native + +# Include the CoAP implementation +MODULES += os/net/app-layer/coap + +# Include CoAP resources +MODULES_REL += ./resources + +CONTIKI=../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/coap/plugtest-server.c b/examples/coap/coap-plugtest-server/coap-plugtest-server.c similarity index 65% rename from examples/coap/plugtest-server.c rename to examples/coap/coap-plugtest-server/coap-plugtest-server.c index c6c0e534f00bfdcb3b61f765a9af78e70a895250..4b6c6d55755d274d93150ee5990a1826a7e76efa 100644 --- a/examples/coap/plugtest-server.c +++ b/examples/coap/coap-plugtest-server/coap-plugtest-server.c @@ -44,15 +44,19 @@ #include "coap.h" #include "coap-transactions.h" #include "coap-separate.h" -#include "rest-engine.h" -#include "plugtest.h" +#include "coap-engine.h" + +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST /* * Resources to be activated need to be imported through the extern keyword. * The build system automatically compiles the resources in the corresponding * sub-directory. */ -extern resource_t +extern coap_resource_t res_plugtest_test, res_plugtest_validate, res_plugtest_create1, @@ -80,44 +84,32 @@ PROCESS_THREAD(plugtest_server, ev, data) { PROCESS_BEGIN(); - PRINTF("ETSI IoT CoAP Plugtests Server\n"); - -#ifdef RF_CHANNEL - PRINTF("RF channel: %u\n", RF_CHANNEL); -#endif -#ifdef IEEE802154_PANID - PRINTF("PAN ID: 0x%04X\n", IEEE802154_PANID); -#endif - - PRINTF("uIP buffer: %u\n", UIP_BUFSIZE); - PRINTF("LL header: %u\n", UIP_LLH_LEN); - PRINTF("IP+UDP header: %u\n", UIP_IPUDPH_LEN); - PRINTF("REST max chunk: %u\n", REST_MAX_CHUNK_SIZE); + LOG_INFO("ETSI IoT CoAP Plugtests Server\n"); /* Initialize the REST engine. */ - rest_init_engine(); + coap_engine_init(); /* Activate the application-specific resources. */ - rest_activate_resource(&res_plugtest_test, "test"); - rest_activate_resource(&res_plugtest_validate, "validate"); - rest_activate_resource(&res_plugtest_create1, "create1"); - rest_activate_resource(&res_plugtest_create2, "create2"); - rest_activate_resource(&res_plugtest_create3, "create3"); - rest_activate_resource(&res_plugtest_longpath, "seg1/seg2/seg3"); - rest_activate_resource(&res_plugtest_query, "query"); - rest_activate_resource(&res_plugtest_locquery, "location-query"); - rest_activate_resource(&res_plugtest_multi, "multi-format"); - rest_activate_resource(&res_plugtest_link1, "link1"); - rest_activate_resource(&res_plugtest_link2, "link2"); - rest_activate_resource(&res_plugtest_link3, "link3"); - rest_activate_resource(&res_plugtest_path, "path"); - rest_activate_resource(&res_plugtest_separate, "separate"); - rest_activate_resource(&res_plugtest_large, "large"); - rest_activate_resource(&res_plugtest_large_update, "large-update"); - rest_activate_resource(&res_plugtest_large_create, "large-create"); - rest_activate_resource(&res_plugtest_obs, "obs"); + coap_activate_resource(&res_plugtest_test, "test"); + coap_activate_resource(&res_plugtest_validate, "validate"); + coap_activate_resource(&res_plugtest_create1, "create1"); + coap_activate_resource(&res_plugtest_create2, "create2"); + coap_activate_resource(&res_plugtest_create3, "create3"); + coap_activate_resource(&res_plugtest_longpath, "seg1/seg2/seg3"); + coap_activate_resource(&res_plugtest_query, "query"); + coap_activate_resource(&res_plugtest_locquery, "location-query"); + coap_activate_resource(&res_plugtest_multi, "multi-format"); + coap_activate_resource(&res_plugtest_link1, "link1"); + coap_activate_resource(&res_plugtest_link2, "link2"); + coap_activate_resource(&res_plugtest_link3, "link3"); + coap_activate_resource(&res_plugtest_path, "path"); + coap_activate_resource(&res_plugtest_separate, "separate"); + coap_activate_resource(&res_plugtest_large, "large"); + coap_activate_resource(&res_plugtest_large_update, "large-update"); + coap_activate_resource(&res_plugtest_large_create, "large-create"); + coap_activate_resource(&res_plugtest_obs, "obs"); - rest_activate_resource(&res_mirror, "mirror"); + coap_activate_resource(&res_mirror, "mirror"); /* Define application-specific events here. */ while(1) { diff --git a/tools/collect-view/src/org/contikios/contiki/collect/Configurable.java b/examples/coap/coap-plugtest-server/project-conf.h similarity index 71% rename from tools/collect-view/src/org/contikios/contiki/collect/Configurable.java rename to examples/coap/coap-plugtest-server/project-conf.h index 285bcca915aca9840230349efb1eb97ddd88ec84..5c86ae985e47bd46302f3c1cbd567bb2022255d2 100644 --- a/tools/collect-view/src/org/contikios/contiki/collect/Configurable.java +++ b/examples/coap/coap-plugtest-server/project-conf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Swedish Institute of Computer Science. + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,25 +26,27 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * - * ----------------------------------------------------------------- - * - * Configurable - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 24 sep 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ + * This file is part of the Contiki operating system. */ -package org.contikios.contiki.collect; -import java.util.Properties; - /** - * + * \file + * Erbium (Er) CoAP client example + * \author + * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ -public interface Configurable { - public void updateConfig(Properties config); +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#define LOG_LEVEL_PLUGTEST LOG_LEVEL_DBG + +/* double expansion */ +#define TO_STRING2(x) # x +#define TO_STRING(x) TO_STRING2(x) + +#define MAX_PLUGFEST_PAYLOAD 64 + 1 /* +1 for the terminating zero, which is not transmitted */ +#define MAX_PLUGFEST_BODY 2048 +#define CHUNKS_TOTAL 2012 -} +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/coap/coap-plugtest-server/resources/res-mirror.c b/examples/coap/coap-plugtest-server/resources/res-mirror.c new file mode 100644 index 0000000000000000000000000000000000000000..ea9ddd3ad437e93ba48f6b980086035d292c25c9 --- /dev/null +++ b/examples/coap/coap-plugtest-server/resources/res-mirror.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Example resource + * \author + * Matthias Kovatsch <kovatsch@inf.ethz.ch> + */ + +#include <stdio.h> +#include <string.h> +#include "coap-engine.h" +#include "coap.h" + +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST + +static void res_any_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); + +/* This resource mirrors the incoming request. It shows how to access the options and how to set them for the response. */ +RESOURCE(res_mirror, + "title=\"Returns your decoded message\";rt=\"Debug\"", + res_any_handler, + res_any_handler, + res_any_handler, + res_any_handler); + +static void +res_any_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + /* The ETag and Token is copied to the header. */ + uint8_t opaque[] = { 0x0A, 0xBC, 0xDE }; + + /* Strings are not copied, so use static string buffers or strings in .text memory (char *str = "string in .text";). */ + static char location[] = { '/', 'f', '/', 'a', '?', 'k', '&', 'e', 0 }; + + /* No default my be assumed for the Content-Format. (Unsigned -1 means all bits set.) */ + unsigned int content_format = -1; + + /* The other getters copy the value (or string/array pointer) to the given pointers and return 1 for success or the length of strings/arrays. */ + uint32_t longint = 0; + const char *str = NULL; + const uint8_t *bytes = NULL; + uint32_t block_num = 0; + uint8_t block_more = 0; + uint16_t block_size = 0; + int len = 0; + + /* Mirror the received header options in the response payload. Unsupported getters (e.g., rest_get_header_observe() with HTTP) will return 0. */ + + int strpos = 0; + /* snprintf() counts the terminating '\0' to the size parameter. + * The additional byte is taken care of by allocating REST_MAX_CHUNK_SIZE+1 bytes in the REST framework. + * Add +1 to fill the complete buffer, as the payload does not need a terminating '\0'. */ + if(coap_get_header_content_format(request, &content_format)) { + strpos += snprintf((char *)buffer, REST_MAX_CHUNK_SIZE + 1, "CF %u\n", content_format); + } + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_accept(request, &content_format))) { + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "Ac %u\n", content_format); + /* Some getters such as for ETag or Location are omitted, as these options should not appear in a request. + * Max-Age might appear in HTTP requests or used for special purposes in CoAP. */ + } + if(strpos <= REST_MAX_CHUNK_SIZE && coap_get_header_max_age(request, &longint)) { + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "MA %lu\n", (unsigned long) longint); + /* For HTTP this is the Length option, for CoAP it is the Size option. */ + } + if(strpos <= REST_MAX_CHUNK_SIZE && coap_get_header_size1(request, &longint)) { + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "SZ %lu\n", (unsigned long) longint); + } + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_uri_host(request, &str))) { + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "UH %.*s\n", len, str); + } + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_uri_path(request, &str))) { + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "UP %.*s\n", len, str); + } + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_uri_query(request, &str))) { + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "UQ %.*s\n", len, str); + /* Undefined request options for debugging: actions not required for normal RESTful Web service. */ + } + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_location_path(request, &str))) { + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "LP %.*s\n", len, str); + } + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_header_location_query(request, &str))) { + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "LQ %.*s\n", len, str); + /* CoAP-specific example: actions not required for normal RESTful Web service. */ + } + coap_message_t *const coap_pkt = (coap_message_t *)request; + + if(strpos <= REST_MAX_CHUNK_SIZE && coap_pkt->token_len > 0) { + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "To 0x"); + int index = 0; + for(index = 0; index < coap_pkt->token_len; ++index) { + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "%02X", coap_pkt->token[index]); + } + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "\n"); + } + + if(strpos <= REST_MAX_CHUNK_SIZE && coap_is_option(coap_pkt, COAP_OPTION_OBSERVE)) { + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "Ob %lu\n", (unsigned long) coap_pkt->observe); + } + if(strpos <= REST_MAX_CHUNK_SIZE && coap_is_option(coap_pkt, COAP_OPTION_ETAG)) { + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "ET 0x"); + int index = 0; + for(index = 0; index < coap_pkt->etag_len; ++index) { + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "%02X", coap_pkt->etag[index]); + } + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "\n"); + } + if(strpos <= REST_MAX_CHUNK_SIZE && coap_get_header_block2(request, &block_num, &block_more, &block_size, NULL)) { /* This getter allows NULL pointers to get only a subset of the block parameters. */ + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "B2 %lu%s (%u)\n", (unsigned long) block_num, block_more ? "+" : "", block_size); + } + if(strpos <= REST_MAX_CHUNK_SIZE && coap_get_header_block1(request, &block_num, &block_more, &block_size, NULL)) { + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "B1 %lu%s (%u)\n", (unsigned long) block_num, block_more ? "+" : "", block_size); + } + if(strpos <= REST_MAX_CHUNK_SIZE && (len = coap_get_payload(request, &bytes))) { + strpos += snprintf((char *)buffer + strpos, REST_MAX_CHUNK_SIZE - strpos + 1, "%.*s", len, bytes); + } + if(strpos >= REST_MAX_CHUNK_SIZE) { + buffer[REST_MAX_CHUNK_SIZE - 1] = 0xBB; /* '»' to indicate truncation */ + } + coap_set_payload(response, buffer, strpos); + + LOG_DBG("/mirror options received: %s\n", buffer); + + /* Set dummy header options for response. Like getters, some setters are not implemented for HTTP and have no effect. */ + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_header_max_age(response, 17); /* For HTTP, browsers will not re-request the page for 17 seconds. */ + coap_set_header_etag(response, opaque, 2); + coap_set_header_location_path(response, location); /* Initial slash is omitted by framework */ + coap_set_header_size1(response, strpos); /* For HTTP, browsers will not re-request the page for 10 s. CoAP action depends on the client. */ + +/* CoAP-specific example: actions not required for normal RESTful Web service. */ + coap_set_header_uri_host(response, "tiki"); + coap_set_header_observe(response, 10); + coap_set_header_proxy_uri(response, "ftp://x"); + coap_set_header_block2(response, 42, 0, 64); /* The block option might be overwritten by the framework when blockwise transfer is requested. */ + coap_set_header_block1(response, 23, 0, 16); + coap_set_header_accept(response, TEXT_PLAIN); + coap_set_header_if_none_match(response); +} diff --git a/examples/coap/resources/res-plugtest-create1.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-create1.c similarity index 69% rename from examples/coap/resources/res-plugtest-create1.c rename to examples/coap/coap-plugtest-server/resources/res-plugtest-create1.c index 4e8c522316cca4d33e4f351e233fda02a0d477ee..fe57e4961e662f191b90b8671e70f9ef81ece81b 100644 --- a/examples/coap/resources/res-plugtest-create1.c +++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-create1.c @@ -37,12 +37,16 @@ */ #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -#include "plugtest.h" -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST + +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_create1, "title=\"Creates on PUT\"", @@ -54,27 +58,27 @@ RESOURCE(res_plugtest_create1, static uint8_t create1_exists = 0; static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - PRINTF("/create1 PUT"); + LOG_DBG("/create1 PUT"); if(coap_get_header_if_none_match(request)) { if(!create1_exists) { - REST.set_response_status(response, REST.status.CREATED); + coap_set_status_code(response, CREATED_2_01); create1_exists = 1; } else { - REST.set_response_status(response, PRECONDITION_FAILED_4_12); + coap_set_status_code(response, PRECONDITION_FAILED_4_12); } } else { - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); } } static void -res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - PRINTF("/create1 DELETE "); - REST.set_response_status(response, REST.status.DELETED); + LOG_DBG("/create1 DELETE "); + coap_set_status_code(response, DELETED_2_02); create1_exists = 0; } diff --git a/examples/coap/resources/res-plugtest-create2.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-create2.c similarity index 77% rename from examples/coap/resources/res-plugtest-create2.c rename to examples/coap/coap-plugtest-server/resources/res-plugtest-create2.c index 714432ff6b6900d1b273a7019270fe3dc7fa0ad7..b4520d6724c7f17328b15a0d419e70ea79b15824 100644 --- a/examples/coap/resources/res-plugtest-create2.c +++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-create2.c @@ -37,11 +37,15 @@ */ #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -#include "plugtest.h" -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST + +static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_create2, "title=\"Creates on POST\"", @@ -51,10 +55,10 @@ RESOURCE(res_plugtest_create2, NULL); static void -res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - PRINTF("/create2 "); + LOG_DBG("/create2 "); - REST.set_response_status(response, REST.status.CREATED); - REST.set_header_location(response, "/location1/location2/location3"); + coap_set_status_code(response, CREATED_2_01); + coap_set_header_location_path(response, "/location1/location2/location3"); } diff --git a/examples/coap/resources/res-plugtest-create3.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-create3.c similarity index 69% rename from examples/coap/resources/res-plugtest-create3.c rename to examples/coap/coap-plugtest-server/resources/res-plugtest-create3.c index fe7526eba6f0ace10bceed738ce586cc546df4be..b78fca67ef88a0d4d2c2d2a7d0867fff957a9e47 100644 --- a/examples/coap/resources/res-plugtest-create3.c +++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-create3.c @@ -37,12 +37,16 @@ */ #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -#include "plugtest.h" -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST + +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_create3, "title=\"Default test resource\"", @@ -54,27 +58,27 @@ RESOURCE(res_plugtest_create3, static uint8_t create3_exists = 0; static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - PRINTF("/create3 PUT "); + LOG_DBG("/create3 PUT "); if(coap_get_header_if_none_match(request)) { if(!create3_exists) { - REST.set_response_status(response, REST.status.CREATED); + coap_set_status_code(response, CREATED_2_01); create3_exists = 1; } else { - REST.set_response_status(response, PRECONDITION_FAILED_4_12); + coap_set_status_code(response, PRECONDITION_FAILED_4_12); } } else { - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); } } static void -res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - PRINTF("/create3 DELETE "); - REST.set_response_status(response, REST.status.DELETED); + LOG_DBG("/create3 DELETE "); + coap_set_status_code(response, DELETED_2_02); create3_exists = 0; } diff --git a/examples/coap/resources/res-plugtest-large-create.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-large-create.c similarity index 70% rename from examples/coap/resources/res-plugtest-large-create.c rename to examples/coap/coap-plugtest-server/resources/res-plugtest-large-create.c index ac1e27a3d3fc6938812d04f24c5c2b8125152b73..923702f5138e5ac1c6c009e7f8b8bd425903542d 100644 --- a/examples/coap/resources/res-plugtest-large-create.c +++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-large-create.c @@ -37,11 +37,15 @@ */ #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -#include "plugtest.h" -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST + +static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* * Large resource that can be created using POST method @@ -54,38 +58,38 @@ RESOURCE(res_plugtest_large_create, NULL); static void -res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; uint8_t *incoming = NULL; size_t len = 0; unsigned int ct = -1; - if(!REST.get_header_content_type(request, &ct)) { - REST.set_response_status(response, REST.status.BAD_REQUEST); + if(!coap_get_header_content_format(request, &ct)) { + coap_set_status_code(response, BAD_REQUEST_4_00); const char *error_msg = "NoContentType"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } - if((len = REST.get_request_payload(request, (const uint8_t **)&incoming))) { + if((len = coap_get_payload(request, (const uint8_t **)&incoming))) { if(coap_req->block1_num * coap_req->block1_size + len <= 2048) { - REST.set_response_status(response, REST.status.CREATED); - REST.set_header_location(response, "/nirvana"); + coap_set_status_code(response, CREATED_2_01); + coap_set_header_location_path(response, "/nirvana"); coap_set_header_block1(response, coap_req->block1_num, 0, coap_req->block1_size); } else { - REST.set_response_status(response, REST.status.REQUEST_ENTITY_TOO_LARGE); + coap_set_status_code(response, REQUEST_ENTITY_TOO_LARGE_4_13); const char *error_msg = "2048B max."; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } } else { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); const char *error_msg = "NoPayload"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } } diff --git a/examples/coap/resources/res-plugtest-large-update.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-large-update.c similarity index 70% rename from examples/coap/resources/res-plugtest-large-update.c rename to examples/coap/coap-plugtest-server/resources/res-plugtest-large-update.c index 8263ccc2af89bba95812e521c5d23e3ba1c17792..289fbdfdf28813fffe4c6a6c6139ab1a7220f9f2 100644 --- a/examples/coap/resources/res-plugtest-large-update.c +++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-large-update.c @@ -36,14 +36,19 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +#include <stdio.h> #include <string.h> #include "sys/cc.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -#include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST + +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE( res_plugtest_large_update, @@ -58,21 +63,21 @@ static uint8_t large_update_store[MAX_PLUGFEST_BODY] = { 0 }; static unsigned int large_update_ct = APPLICATION_OCTET_STREAM; static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* Check the offset for boundaries of the resource data. */ if(*offset >= large_update_size) { - REST.set_response_status(response, REST.status.BAD_OPTION); + coap_set_status_code(response, BAD_OPTION_4_02); /* A block error message should not exceed the minimum block size (16). */ const char *error_msg = "BlockOutOfScope"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } - REST.set_response_payload(response, large_update_store + *offset, + coap_set_payload(response, large_update_store + *offset, MIN(large_update_size - *offset, preferred_size)); - REST.set_header_content_type(response, large_update_ct); + coap_set_header_content_format(response, large_update_ct); /* IMPORTANT for chunk-wise resources: Signal chunk awareness to REST engine. */ *offset += preferred_size; @@ -83,22 +88,22 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr } } static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; uint8_t *incoming = NULL; size_t len = 0; unsigned int ct = -1; - if(!REST.get_header_content_type(request, &ct)) { - REST.set_response_status(response, REST.status.BAD_REQUEST); + if(!coap_get_header_content_format(request, &ct)) { + coap_set_status_code(response, BAD_REQUEST_4_00); const char *error_msg = "NoContentType"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } - if((len = REST.get_request_payload(request, (const uint8_t **)&incoming))) { + if((len = coap_get_payload(request, (const uint8_t **)&incoming))) { if(coap_req->block1_num * coap_req->block1_size + len <= sizeof(large_update_store)) { memcpy( large_update_store + coap_req->block1_num * coap_req->block1_size, @@ -106,13 +111,13 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr large_update_size = coap_req->block1_num * coap_req->block1_size + len; large_update_ct = ct; - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); coap_set_header_block1(response, coap_req->block1_num, 0, coap_req->block1_size); } else { - REST.set_response_status(response, - REST.status.REQUEST_ENTITY_TOO_LARGE); - REST.set_response_payload( + coap_set_status_code(response, + REQUEST_ENTITY_TOO_LARGE_4_13); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "%uB max.", @@ -120,9 +125,9 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr return; } } else { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); const char *error_msg = "NoPayload"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } } diff --git a/examples/coap/resources/res-plugtest-large.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-large.c similarity index 82% rename from examples/coap/resources/res-plugtest-large.c rename to examples/coap/coap-plugtest-server/resources/res-plugtest-large.c index 8a7372eb83949b35799e5771090aa28785a0ab6c..850f88461cdfa8453749068157b38f58aad9be17 100644 --- a/examples/coap/resources/res-plugtest-large.c +++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-large.c @@ -36,12 +36,17 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -#include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST + +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_large, "title=\"Large resource\";rt=\"block\";sz=\"" TO_STRING(CHUNKS_TOTAL) "\"", @@ -51,17 +56,17 @@ RESOURCE(res_plugtest_large, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int32_t strpos = 0; /* Check the offset for boundaries of the resource data. */ if(*offset >= CHUNKS_TOTAL) { - REST.set_response_status(response, REST.status.BAD_OPTION); + coap_set_status_code(response, BAD_OPTION_4_02); /* A block error message should not exceed the minimum block size (16). */ const char *error_msg = "BlockOutOfScope"; - REST.set_response_payload(response, error_msg, strlen(error_msg)); + coap_set_payload(response, error_msg, strlen(error_msg)); return; } @@ -79,8 +84,8 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr if(*offset + (int32_t)strpos > CHUNKS_TOTAL) { strpos = CHUNKS_TOTAL - *offset; } - REST.set_response_payload(response, buffer, strpos); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + coap_set_payload(response, buffer, strpos); + coap_set_header_content_format(response, TEXT_PLAIN); /* IMPORTANT for chunk-wise resources: Signal chunk awareness to REST engine. */ *offset += strpos; diff --git a/examples/coap/resources/res-plugtest-links.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-links.c similarity index 81% rename from examples/coap/resources/res-plugtest-links.c rename to examples/coap/coap-plugtest-server/resources/res-plugtest-links.c index f802d3c566be8dcfa5893b51222ae55a22707f0d..3bbd2a0623d5120a67dff96c7e9bdd6affac9288 100644 --- a/examples/coap/resources/res-plugtest-links.c +++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-links.c @@ -37,11 +37,15 @@ */ #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -#include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST + +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_link1, "rt=\"Type1 Type2\";if=\"If1\"", @@ -63,9 +67,9 @@ RESOURCE(res_plugtest_link3, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *msg = "Dummy link"; - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, msg, strlen(msg)); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, msg, strlen(msg)); } diff --git a/examples/coap/resources/res-plugtest-locquery.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-locquery.c similarity index 77% rename from examples/coap/resources/res-plugtest-locquery.c rename to examples/coap/coap-plugtest-server/resources/res-plugtest-locquery.c index d75a9a6208c8cbd98147ebd365d1df9c29f67a2b..e7163e8b1bff553055c1feecbadac073a2b8861b 100644 --- a/examples/coap/resources/res-plugtest-locquery.c +++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-locquery.c @@ -37,11 +37,15 @@ */ #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -#include "plugtest.h" -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST + +static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_locquery, "title=\"Resource accepting query parameters\"", @@ -51,15 +55,13 @@ RESOURCE(res_plugtest_locquery, NULL); static void -res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { -#if DEBUG - coap_packet_t *const coap_req = (coap_packet_t *)request; -#endif + coap_message_t *const coap_req = (coap_message_t *)request; - PRINTF( + LOG_DBG( "/location-query POST (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); - REST.set_response_status(response, REST.status.CREATED); - REST.set_header_location(response, "?first=1&second=2"); + coap_set_status_code(response, CREATED_2_01); + coap_set_header_location_query(response, "?first=1&second=2"); } diff --git a/examples/coap/resources/res-plugtest-longpath.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-longpath.c similarity index 76% rename from examples/coap/resources/res-plugtest-longpath.c rename to examples/coap/coap-plugtest-server/resources/res-plugtest-longpath.c index 5a26d4db9530670a3bfe86a4bf600694e9da9d76..990ad267779ef7977656c15718097b81ce92b24c 100644 --- a/examples/coap/resources/res-plugtest-longpath.c +++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-longpath.c @@ -36,12 +36,18 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ + +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -#include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST + +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_longpath, "title=\"Long path resource\"", @@ -51,18 +57,18 @@ RESOURCE(res_plugtest_longpath, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; - PRINTF("/seg1/seg2/seg3 GET "); + LOG_DBG("/seg1/seg2/seg3 GET "); /* Code 2.05 CONTENT is default. */ - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload( + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "Type: %u\nCode: %u\nMID: %u", coap_req->type, coap_req->code, coap_req->mid)); - PRINTF("(%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); + LOG_DBG_("(%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); } diff --git a/examples/coap/resources/res-plugtest-multi.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-multi.c similarity index 70% rename from examples/coap/resources/res-plugtest-multi.c rename to examples/coap/coap-plugtest-server/resources/res-plugtest-multi.c index c6592b397a02278e98f89753cbe01e6b765cef86..9606d91a66b094be8f21bc157071371b3b27a195 100644 --- a/examples/coap/resources/res-plugtest-multi.c +++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-multi.c @@ -36,12 +36,17 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -#include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST + +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_multi, "title=\"Resource providing text/plain and application/xml\";ct=\"0 41\"", @@ -51,37 +56,37 @@ RESOURCE(res_plugtest_multi, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - PRINTF("/multi-format GET (%s %u) ", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); + LOG_DBG("/multi-format GET (%s %u) ", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload( + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "Type: %u\nCode: %u\nMID: %u%s", coap_req->type, coap_req->code, coap_req->mid, accept != -1 ? "\nAccept: 0" : "")); - PRINTF("PLAIN\n"); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); - REST.set_response_payload( + LOG_DBG_("PLAIN\n"); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "<status type=\"%u\" code=\"%u\" mid=\"%u\" accept=\"%u\"/>", coap_req->type, coap_req->code, coap_req->mid, accept)); - PRINTF("XML\n"); + LOG_DBG_("XML\n"); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); const char *msg = "Supporting content-types text/plain and application/xml"; - REST.set_response_payload(response, msg, strlen(msg)); - PRINTF("ERROR\n"); + coap_set_payload(response, msg, strlen(msg)); + LOG_DBG_("ERROR\n"); } } diff --git a/examples/coap/resources/res-plugtest-obs.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-obs.c similarity index 65% rename from examples/coap/resources/res-plugtest-obs.c rename to examples/coap/coap-plugtest-server/resources/res-plugtest-obs.c index 74d61d8942e6de40386109d2a023722d7f7722e2..7d191e7516797f04a7e809765e44417a0d4b6077 100644 --- a/examples/coap/resources/res-plugtest-obs.c +++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-obs.c @@ -36,15 +36,20 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "coap-observe.h" -#include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST + +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_periodic_handler(void); PERIODIC_RESOURCE(res_plugtest_obs, @@ -66,83 +71,81 @@ static char obs_status = 0; static void obs_purge_list() { - PRINTF("### SERVER ACTION ### Purging obs list"); - coap_remove_observer_by_uri(NULL, 0, res_plugtest_obs.url); + LOG_DBG("### SERVER ACTION ### Purging obs list\n"); + coap_remove_observer_by_uri(NULL, res_plugtest_obs.url); } static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* Keep server log clean from ticking events */ if(request != NULL) { - PRINTF("/obs GET\n"); + LOG_DBG("/obs GET\n"); } - REST.set_header_content_type(response, obs_format); - REST.set_header_max_age(response, 5); + coap_set_header_content_format(response, obs_format); + coap_set_header_max_age(response, 5); if(obs_content_len) { - REST.set_header_content_type(response, obs_format); - REST.set_response_payload(response, obs_content, obs_content_len); + coap_set_header_content_format(response, obs_format); + coap_set_payload(response, obs_content, obs_content_len); } else { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, obs_content, + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, obs_content, snprintf(obs_content, MAX_PLUGFEST_PAYLOAD, "TICK %lu", (unsigned long) obs_counter)); } - /* A post_handler that handles subscriptions will be called for periodic resources by the REST framework. */ + /* A post_handler that handles subscriptions will be called for periodic resources by the CoAP framework. */ } static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { uint8_t *incoming = NULL; unsigned int ct = -1; - REST.get_header_content_type(request, &ct); + coap_get_header_content_format(request, &ct); - PRINTF("/obs PUT\n"); + LOG_DBG("/obs PUT\n"); if(ct != obs_format) { obs_status = 1; obs_format = ct; } else { - obs_content_len = REST.get_request_payload(request, + obs_content_len = coap_get_payload(request, (const uint8_t **)&incoming); memcpy(obs_content, incoming, obs_content_len); res_periodic_handler(); } - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); } static void -res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - PRINTF("/obs DELETE\n"); + LOG_DBG("/obs DELETE\n"); obs_status = 2; - REST.set_response_status(response, REST.status.DELETED); + coap_set_status_code(response, DELETED_2_02); } /* * Additionally, a handler function named [resource name]_handler must be implemented for each PERIODIC_RESOURCE. - * It will be called by the REST manager process with the defined period. + * It will be called by the CoAP manager process with the defined period. */ static void res_periodic_handler() { ++obs_counter; - /* PRINTF("TICK %u for /%s\n", obs_counter, r->url); */ - if(obs_status == 1) { /* Notify the registered observers with the given message type, observe option, and payload. */ - REST.notify_subscribers(&res_plugtest_obs); + coap_notify_observers(&res_plugtest_obs); - PRINTF("######### sending 5.00\n"); + LOG_DBG("######### sending 5.00\n"); obs_purge_list(); } else if(obs_status == 2) { /* Notify the registered observers with the given message type, observe option, and payload. */ - REST.notify_subscribers(&res_plugtest_obs); + coap_notify_observers(&res_plugtest_obs); obs_purge_list(); @@ -150,6 +153,6 @@ res_periodic_handler() obs_content_len = 0; } else { /* Notify the registered observers with the given message type, observe option, and payload. */ - REST.notify_subscribers(&res_plugtest_obs); + coap_notify_observers(&res_plugtest_obs); } obs_status = 0; } diff --git a/examples/coap/resources/res-plugtest-path.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-path.c similarity index 79% rename from examples/coap/resources/res-plugtest-path.c rename to examples/coap/coap-plugtest-server/resources/res-plugtest-path.c index 03eb362bb1a89f32b356cd55e44d4957236be820..767609f096c4186dda11a13bc85e9f41d0dd3166 100644 --- a/examples/coap/resources/res-plugtest-path.c +++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-path.c @@ -36,12 +36,17 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -#include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST + +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); PARENT_RESOURCE(res_plugtest_path, "title=\"Path test resource\";ct=\"40\"", @@ -51,22 +56,22 @@ PARENT_RESOURCE(res_plugtest_path, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *uri_path = NULL; - int len = REST.get_url(request, &uri_path); + int len = coap_get_header_uri_path(request, &uri_path); int base_len = strlen(res_plugtest_path.url); if(len == base_len) { - REST.set_header_content_type(response, REST.type.APPLICATION_LINK_FORMAT); + coap_set_header_content_format(response, APPLICATION_LINK_FORMAT); snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "</path/sub1>,</path/sub2>,</path/sub3>"); } else { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + coap_set_header_content_format(response, TEXT_PLAIN); snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "/%.*s", len, uri_path); } - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } diff --git a/examples/coap/resources/res-plugtest-query.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-query.c similarity index 77% rename from examples/coap/resources/res-plugtest-query.c rename to examples/coap/coap-plugtest-server/resources/res-plugtest-query.c index 6ffbccbbb69fceca2667ef9af745123a25077797..1080d31624a937229b059fdb684330b4b4df4b81 100644 --- a/examples/coap/resources/res-plugtest-query.c +++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-query.c @@ -36,12 +36,17 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -#include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST + +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_query, "title=\"Resource accepting query parameters\"", @@ -51,22 +56,22 @@ RESOURCE(res_plugtest_query, NULL); static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; int len = 0; const char *query = NULL; - PRINTF( + LOG_DBG( "/query GET (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); - if((len = REST.get_query(request, &query))) { - PRINTF("Query: %.*s\n", len, query); + if((len = coap_get_header_uri_query(request, &query))) { + LOG_DBG("Query: %.*s\n", len, query); /* Code 2.05 CONTENT is default. */ } - REST.set_header_content_type(response, - REST.type.TEXT_PLAIN); - REST.set_response_payload( + coap_set_header_content_format(response, + TEXT_PLAIN); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, diff --git a/examples/coap/resources/res-plugtest-separate.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-separate.c similarity index 82% rename from examples/coap/resources/res-plugtest-separate.c rename to examples/coap/coap-plugtest-server/resources/res-plugtest-separate.c index b45841ec10b03dfceb1ba260dba17b250dd0e863..c0ae81d114fe807bb6e1108cacd95cb6023770d2 100644 --- a/examples/coap/resources/res-plugtest-separate.c +++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-separate.c @@ -36,14 +36,19 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "coap-transactions.h" #include "coap-separate.h" -#include "plugtest.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST + +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_resume_handler(void); PERIODIC_RESOURCE(res_plugtest_separate, @@ -67,16 +72,16 @@ static uint8_t separate_active = 0; static application_separate_store_t separate_store[1]; void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; - PRINTF("/separate "); + LOG_DBG("/separate "); if(separate_active) { - PRINTF("REJECTED "); + LOG_DBG_("REJECTED "); coap_separate_reject(); } else { - PRINTF("STORED "); + LOG_DBG_("STORED "); separate_active = 1; /* Take over and skip response by engine. */ @@ -88,26 +93,25 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr coap_req->mid); } - PRINTF("(%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); + LOG_DBG_("(%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); } static void res_resume_handler() { if(separate_active) { - PRINTF("/separate "); + LOG_DBG("/separate "); coap_transaction_t *transaction = NULL; if((transaction = coap_new_transaction(separate_store->request_metadata.mid, - &separate_store->request_metadata.addr, - separate_store->request_metadata.port))) { - PRINTF( + &separate_store->request_metadata.endpoint))) { + LOG_DBG_( "RESPONSE (%s %u)\n", separate_store->request_metadata.type == COAP_TYPE_CON ? "CON" : "NON", separate_store->request_metadata.mid); - coap_packet_t response[1]; /* This way the packet can be treated as pointer as usual. */ + coap_message_t response[1]; /* This way the message can be treated as pointer as usual. */ /* Restore the request information for the response. */ coap_separate_resume(response, &separate_store->request_metadata, CONTENT_2_05); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + coap_set_header_content_format(response, TEXT_PLAIN); coap_set_payload(response, separate_store->buffer, strlen(separate_store->buffer)); @@ -120,14 +124,14 @@ res_resume_handler() separate_store->request_metadata.block2_size); /* Warning: No check for serialization error. */ - transaction->packet_len = coap_serialize_message(response, - transaction->packet); + transaction->message_len = coap_serialize_message(response, + transaction->message); coap_send_transaction(transaction); /* The engine will clear the transaction (right after send for NON, after acked for CON). */ separate_active = 0; } else { - PRINTF("ERROR (transaction)\n"); + LOG_DBG_("ERROR (transaction)\n"); } } /* if (separate_active) */ } diff --git a/examples/coap/resources/res-plugtest-test.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-test.c similarity index 51% rename from examples/coap/resources/res-plugtest-test.c rename to examples/coap/coap-plugtest-server/resources/res-plugtest-test.c index 4af32b9ba5c88aee4a019ab0d2ade3c0b80115ef..d02b3026decd6bb519c9529e6a076e6a6a502ec8 100644 --- a/examples/coap/resources/res-plugtest-test.c +++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-test.c @@ -36,15 +36,21 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -#include "plugtest.h" +#include "random.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST + +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_test, "title=\"Default test resource\"", res_get_handler, res_post_handler, res_put_handler, res_delete_handler); @@ -66,97 +72,91 @@ test_update_etag() } test_change = 0; - PRINTF("### SERVER ACTION ### Changed ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", test_etag_len, test_etag[0], test_etag[1], test_etag[2], test_etag[3], test_etag[4], test_etag[5], test_etag[6], test_etag[7]); + LOG_DBG("### SERVER ACTION ### Changed ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", test_etag_len, test_etag[0], test_etag[1], test_etag[2], test_etag[3], test_etag[4], test_etag[5], test_etag[6], test_etag[7]); } static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; if(test_change) { test_update_etag(); } - PRINTF("/test GET (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); + LOG_DBG("/test GET (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); if((len = coap_get_header_etag(request, &bytes)) > 0 && len == test_etag_len && memcmp(test_etag, bytes, len) == 0) { - PRINTF("validate "); - REST.set_response_status(response, REST.status.NOT_MODIFIED); - REST.set_header_etag(response, test_etag, test_etag_len); + LOG_DBG("validate\n"); + coap_set_status_code(response, VALID_2_03); + coap_set_header_etag(response, test_etag, test_etag_len); test_change = 1; - PRINTF("### SERVER ACTION ### Resource will change\n"); + LOG_DBG("### SERVER ACTION ### Resource will change\n"); } else { /* Code 2.05 CONTENT is default. */ - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_header_etag(response, test_etag, test_etag_len); - REST.set_header_max_age(response, 30); - REST.set_response_payload( + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_header_etag(response, test_etag, test_etag_len); + coap_set_header_max_age(response, 30); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, "Type: %u\nCode: %u\nMID: %u", coap_req->type, coap_req->code, coap_req->mid)); } } static void -res_post_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_post_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { -#if DEBUG - coap_packet_t *const coap_req = (coap_packet_t *)request; - PRINTF("/test POST (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); -#endif - REST.set_response_status(response, REST.status.CREATED); - REST.set_header_location(response, "/location1/location2/location3"); + coap_message_t *const coap_req = (coap_message_t *)request; + LOG_DBG("/test POST (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); + coap_set_status_code(response, CREATED_2_01); + coap_set_header_location_path(response, "/location1/location2/location3"); } static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { -#if DEBUG - coap_packet_t *const coap_req = (coap_packet_t *)request; - PRINTF("/test PUT (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); -#endif + coap_message_t *const coap_req = (coap_message_t *)request; + LOG_DBG("/test PUT (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); if(coap_get_header_if_none_match(request)) { if(test_none_match_okay) { - REST.set_response_status(response, REST.status.CREATED); + coap_set_status_code(response, CREATED_2_01); test_none_match_okay = 0; - PRINTF("### SERVER ACTION ### If-None-Match will FAIL\n"); + LOG_DBG("### SERVER ACTION ### If-None-Match will FAIL\n"); } else { - REST.set_response_status(response, PRECONDITION_FAILED_4_12); + coap_set_status_code(response, PRECONDITION_FAILED_4_12); test_none_match_okay = 1; - PRINTF("### SERVER ACTION ### If-None-Match will SUCCEED\n"); + LOG_DBG("### SERVER ACTION ### If-None-Match will SUCCEED\n"); } } else if(((len = coap_get_header_if_match(request, &bytes)) > 0 && (len == test_etag_len && memcmp(test_etag, bytes, len) == 0)) || len == 0) { test_update_etag(); - REST.set_header_etag(response, test_etag, test_etag_len); + coap_set_header_etag(response, test_etag, test_etag_len); - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); if(len > 0) { test_change = 1; - PRINTF("### SERVER ACTION ### Resource will change\n"); + LOG_DBG("### SERVER ACTION ### Resource will change\n"); } } else { - PRINTF("Check %u/%u\n [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", - len, - test_etag_len, + LOG_DBG("Check %u/%u\n [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", + (unsigned)len, + (unsigned)test_etag_len, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], test_etag[0], test_etag[1], test_etag[2], test_etag[3], test_etag[4], test_etag[5], test_etag[6], test_etag[7]); - REST.set_response_status(response, PRECONDITION_FAILED_4_12); + coap_set_status_code(response, PRECONDITION_FAILED_4_12); } } static void -res_delete_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_delete_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { -#if DEBUG - coap_packet_t *const coap_req = (coap_packet_t *)request; - PRINTF("/test DELETE (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); -#endif - REST.set_response_status(response, REST.status.DELETED); + coap_message_t *const coap_req = (coap_message_t *)request; + LOG_DBG("/test DELETE (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); + coap_set_status_code(response, DELETED_2_02); } diff --git a/examples/coap/resources/res-plugtest-validate.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-validate.c similarity index 65% rename from examples/coap/resources/res-plugtest-validate.c rename to examples/coap/coap-plugtest-server/resources/res-plugtest-validate.c index ab7b6cfca141be3c793f269f36e0b76a47aee967..7a5920c2bd9a023641e76e2767b003c53e9ca6c8 100644 --- a/examples/coap/resources/res-plugtest-validate.c +++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-validate.c @@ -36,13 +36,19 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +#include <stdio.h> #include <string.h> -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" -#include "plugtest.h" +#include "random.h" -static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "Plugtest" +#define LOG_LEVEL LOG_LEVEL_PLUGTEST + +static void res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); RESOURCE(res_plugtest_validate, "title=\"Validation test resource\"", @@ -68,34 +74,34 @@ validate_update_etag() } validate_change = 0; - PRINTF("### SERVER ACTION ### Changed ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", + LOG_DBG("### SERVER ACTION ### Changed ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", validate_etag_len, validate_etag[0], validate_etag[1], validate_etag[2], validate_etag[3], validate_etag[4], validate_etag[5], validate_etag[6], validate_etag[7]); } static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - coap_packet_t *const coap_req = (coap_packet_t *)request; + coap_message_t *const coap_req = (coap_message_t *)request; if(validate_change) { validate_update_etag(); } - PRINTF("/validate GET"); - PRINTF("(%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); + LOG_DBG("/validate GET"); + LOG_DBG_("(%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); if((len = coap_get_header_etag(request, &bytes)) > 0 && len == validate_etag_len && memcmp(validate_etag, bytes, len) == 0) { - PRINTF("validate "); - REST.set_response_status(response, REST.status.NOT_MODIFIED); - REST.set_header_etag(response, validate_etag, validate_etag_len); + LOG_DBG("validate\n"); + coap_set_status_code(response, VALID_2_03); + coap_set_header_etag(response, validate_etag, validate_etag_len); validate_change = 1; - PRINTF("### SERVER ACTION ### Resouce will change\n"); + LOG_DBG("### SERVER ACTION ### Resouce will change\n"); } else { /* Code 2.05 CONTENT is default. */ - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_header_etag(response, validate_etag, validate_etag_len); - REST.set_header_max_age(response, 30); - REST.set_response_payload( + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_header_etag(response, validate_etag, validate_etag_len); + coap_set_header_max_age(response, 30); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, @@ -104,36 +110,34 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr } } static void -res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_put_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { -#if DEBUG - coap_packet_t *const coap_req = (coap_packet_t *)request; -#endif + coap_message_t *const coap_req = (coap_message_t *)request; - PRINTF("/validate PUT "); - PRINTF("(%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); + LOG_DBG("/validate PUT "); + LOG_DBG_("(%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); if(((len = coap_get_header_if_match(request, &bytes)) > 0 && (len == validate_etag_len && memcmp(validate_etag, bytes, len) == 0)) || len == 0) { validate_update_etag(); - REST.set_header_etag(response, validate_etag, validate_etag_len); + coap_set_header_etag(response, validate_etag, validate_etag_len); - REST.set_response_status(response, REST.status.CHANGED); + coap_set_status_code(response, CHANGED_2_04); if(len > 0) { validate_change = 1; - PRINTF("### SERVER ACTION ### Resouce will change\n"); + LOG_DBG("### SERVER ACTION ### Resouce will change\n"); } } else { - PRINTF( - "Check %u/%u\n [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n [0x%02X%02X%02X%02X%02X%02X%02X%02X] ", - len, - validate_etag_len, + LOG_DBG( + "Check %u/%u\n [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", + (unsigned)len, + (unsigned)validate_etag_len, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], validate_etag[0], validate_etag[1], validate_etag[2], validate_etag[3], validate_etag[4], validate_etag[5], validate_etag[6], validate_etag[7]); - REST.set_response_status(response, PRECONDITION_FAILED_4_12); + coap_set_status_code(response, PRECONDITION_FAILED_4_12); } } diff --git a/examples/coap/in6addr.patch b/examples/coap/in6addr.patch deleted file mode 100644 index 92ca106cfe2a1d75ed78b8a34a7c5a4c9cb29b8a..0000000000000000000000000000000000000000 --- a/examples/coap/in6addr.patch +++ /dev/null @@ -1,10 +0,0 @@ -21,23c21 -< #ifdef __INSIDE_CYGWIN__ -< uint32_t __s6_addr32[4]; -< #endif ---- -> u_int __s6_addr32[4]; -36d33 -< #ifdef __INSIDE_CYGWIN__ -39d35 -< #endif diff --git a/examples/coap/plugtest.h b/examples/coap/plugtest.h deleted file mode 100644 index 78b168d4b70409c13fd4f03aca9aa1cfa61ce54a..0000000000000000000000000000000000000000 --- a/examples/coap/plugtest.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - */ - -/** - * \file - * Erbium (Er) CoAP client example - * \author - * Matthias Kovatsch <kovatsch@inf.ethz.ch> - */ - -#ifndef PLUGTEST_H_ -#define PLUGTEST_H_ - -#if !defined(CONTIKI_TARGET_NATIVE) -#warning "Should only be compiled for native!" -#endif - -#define DEBUG 0 -#if DEBUG -#include <stdio.h> -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif - -/* double expansion */ -#define TO_STRING2(x) # x -#define TO_STRING(x) TO_STRING2(x) - -#define MAX_PLUGFEST_PAYLOAD 64 + 1 /* +1 for the terminating zero, which is not transmitted */ -#define MAX_PLUGFEST_BODY 2048 -#define CHUNKS_TOTAL 2012 - -#endif /* PLUGTEST_H_ */ diff --git a/examples/coap/server-client-native.csc b/examples/coap/server-client-native.csc deleted file mode 100644 index cec9ca8a76851b3cc8c953effdda10a47db32b6c..0000000000000000000000000000000000000000 --- a/examples/coap/server-client-native.csc +++ /dev/null @@ -1,231 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<simconf> - <project EXPORT="discard">[APPS_DIR]/mrm</project> - <project EXPORT="discard">[APPS_DIR]/mspsim</project> - <project EXPORT="discard">[APPS_DIR]/avrora</project> - <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> - <project EXPORT="discard">[APPS_DIR]/powertracker</project> - <simulation> - <title>REST with RPL router</title> - <speedlimit>1.0</speedlimit> - <randomseed>123456</randomseed> - <motedelay_us>1000000</motedelay_us> - <radiomedium> - org.contikios.cooja.radiomediums.UDGM - <transmitting_range>50.0</transmitting_range> - <interference_range>50.0</interference_range> - <success_ratio_tx>1.0</success_ratio_tx> - <success_ratio_rx>1.0</success_ratio_rx> - </radiomedium> - <events> - <logoutput>40000</logoutput> - </events> - <motetype> - org.contikios.cooja.mspmote.SkyMoteType - <identifier>slipradio</identifier> - <description>Sky SLIP radio</description> - <source EXPORT="discard">[CONTIKI_DIR]/examples/ipv6/slip-radio/slip-radio.c</source> - <commands EXPORT="discard">make slip-radio.sky TARGET=sky</commands> - <firmware EXPORT="copy">[CONTIKI_DIR]/examples/ipv6/slip-radio/slip-radio.sky</firmware> - <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface> - </motetype> - <motetype> - org.contikios.cooja.mspmote.SkyMoteType - <identifier>server</identifier> - <description>Erbium Server</description> - <source EXPORT="discard">[CONTIKI_DIR]/examples/coap/coap-example-server.c</source> - <commands EXPORT="discard">make coap-example-server.sky TARGET=sky</commands> - <firmware EXPORT="copy">[CONTIKI_DIR]/examples/coap/coap-example-server.sky</firmware> - <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface> - </motetype> - <motetype> - org.contikios.cooja.mspmote.SkyMoteType - <identifier>client</identifier> - <description>Erbium Client</description> - <source EXPORT="discard">[CONTIKI_DIR]/examples/coap/coap-example-client.c</source> - <commands EXPORT="discard">make coap-example-client.sky TARGET=sky</commands> - <firmware EXPORT="copy">[CONTIKI_DIR]/examples/coap/coap-example-client.sky</firmware> - <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface> - </motetype> - <mote> - <breakpoints /> - <interface_config> - org.contikios.cooja.interfaces.Position - <x>30.303994886410642</x> - <y>17.22128424003353</y> - <z>0.0</z> - </interface_config> - <interface_config> - org.contikios.cooja.mspmote.interfaces.MspMoteID - <id>1</id> - </interface_config> - <motetype_identifier>slipradio</motetype_identifier> - </mote> - <mote> - <breakpoints /> - <interface_config> - org.contikios.cooja.interfaces.Position - <x>46.57186415376375</x> - <y>37.25589203828498</y> - <z>0.0</z> - </interface_config> - <interface_config> - org.contikios.cooja.mspmote.interfaces.MspMoteID - <id>2</id> - </interface_config> - <motetype_identifier>server</motetype_identifier> - </mote> - <mote> - <breakpoints /> - <interface_config> - org.contikios.cooja.interfaces.Position - <x>18.194682268367348</x> - <y>50.210548118402656</y> - <z>0.0</z> - </interface_config> - <interface_config> - org.contikios.cooja.mspmote.interfaces.MspMoteID - <id>3</id> - </interface_config> - <motetype_identifier>client</motetype_identifier> - </mote> - </simulation> - <plugin> - org.contikios.cooja.plugins.SimControl - <width>259</width> - <z>0</z> - <height>179</height> - <location_x>1</location_x> - <location_y>2</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.Visualizer - <plugin_config> - <skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.AttributeVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.LEDVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.AddressVisualizerSkin</skin> - <viewport>2.255467003316979 0.0 0.0 2.255467003316979 59.30641698643764 -13.478401994502008</viewport> - </plugin_config> - <width>300</width> - <z>2</z> - <height>178</height> - <location_x>262</location_x> - <location_y>1</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.LogListener - <plugin_config> - <filter /> - <formatted_time /> - <coloring /> - </plugin_config> - <width>762</width> - <z>4</z> - <height>491</height> - <location_x>2</location_x> - <location_y>182</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.RadioLogger - <plugin_config> - <split>150</split> - <formatted_time /> - <showdups>false</showdups> - <hidenodests>false</hidenodests> - <analyzers name="6lowpan" /> - </plugin_config> - <width>451</width> - <z>-1</z> - <height>305</height> - <location_x>73</location_x> - <location_y>140</location_y> - <minimized>true</minimized> - </plugin> - <plugin> - org.contikios.cooja.plugins.TimeLine - <plugin_config> - <mote>0</mote> - <mote>1</mote> - <mote>2</mote> - <showRadioRXTX /> - <showRadioHW /> - <showLEDs /> - <showWatchpoints /> - <zoomfactor>25.49079397896416</zoomfactor> - </plugin_config> - <width>1624</width> - <z>5</z> - <height>252</height> - <location_x>6</location_x> - <location_y>712</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.MoteInterfaceViewer - <mote_arg>1</mote_arg> - <plugin_config> - <interface>Serial port</interface> - <scrollpos>0,0</scrollpos> - </plugin_config> - <width>853</width> - <z>3</z> - <height>491</height> - <location_x>765</location_x> - <location_y>182</location_y> - </plugin> - <plugin> - org.contikios.cooja.serialsocket.SerialSocketServer - <mote_arg>0</mote_arg> - <width>422</width> - <z>1</z> - <height>82</height> - <location_x>606</location_x> - <location_y>51</location_y> - </plugin> -</simconf> - diff --git a/examples/coap/server-client-observe.csc b/examples/coap/server-client-observe.csc deleted file mode 100644 index a7c9cca8b8409b051c56e5eff56d5f263d120175..0000000000000000000000000000000000000000 --- a/examples/coap/server-client-observe.csc +++ /dev/null @@ -1,203 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<simconf> - <project EXPORT="discard">[APPS_DIR]/mrm</project> - <project EXPORT="discard">[APPS_DIR]/mspsim</project> - <project EXPORT="discard">[APPS_DIR]/avrora</project> - <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> - <project EXPORT="discard">[APPS_DIR]/powertracker</project> - <simulation> - <title>REST with RPL router</title> - <speedlimit>1.0</speedlimit> - <randomseed>123456</randomseed> - <motedelay_us>1000000</motedelay_us> - <radiomedium> - org.contikios.cooja.radiomediums.UDGM - <transmitting_range>50.0</transmitting_range> - <interference_range>50.0</interference_range> - <success_ratio_tx>1.0</success_ratio_tx> - <success_ratio_rx>1.0</success_ratio_rx> - </radiomedium> - <events> - <logoutput>40000</logoutput> - </events> - <motetype> - org.contikios.cooja.mspmote.SkyMoteType - <identifier>rplroot</identifier> - <description>Sky RPL Root</description> - <source EXPORT="discard">[CONTIKI_DIR]/examples/rpl-border-router/border-router.c</source> - <commands EXPORT="discard">make border-router.sky TARGET=sky</commands> - <firmware EXPORT="copy">[CONTIKI_DIR]/examples/rpl-border-router/border-router.sky</firmware> - <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface> - </motetype> - <motetype> - org.contikios.cooja.mspmote.SkyMoteType - <identifier>server</identifier> - <description>Erbium Server</description> - <source EXPORT="discard">[CONTIKI_DIR]/examples/coap/coap-example-server.c</source> - <commands EXPORT="discard">make coap-example-server.sky TARGET=sky</commands> - <firmware EXPORT="copy">[CONTIKI_DIR]/examples/coap/coap-example-server.sky</firmware> - <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface> - </motetype> - <motetype> - org.contikios.cooja.mspmote.SkyMoteType - <identifier>client</identifier> - <description>Erbium Client</description> - <source EXPORT="discard">[CONTIKI_DIR]/examples/coap/coap-example-observe-client.c</source> - <commands EXPORT="discard">make coap-example-observe-client.sky TARGET=sky</commands> - <firmware EXPORT="copy">[CONTIKI_DIR]/examples/coap/coap-example-observe-client.sky</firmware> - <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface> - </motetype> - <mote> - <breakpoints /> - <interface_config> - org.contikios.cooja.interfaces.Position - <x>33.260163187353555</x> - <y>30.643217359962595</y> - <z>0.0</z> - </interface_config> - <interface_config> - org.contikios.cooja.mspmote.interfaces.MspMoteID - <id>1</id> - </interface_config> - <motetype_identifier>rplroot</motetype_identifier> - </mote> - <mote> - <breakpoints /> - <interface_config> - org.contikios.cooja.interfaces.Position - <x>54.537149936813485</x> - <y>51.51086225537906</y> - <z>0.0</z> - </interface_config> - <interface_config> - org.contikios.cooja.mspmote.interfaces.MspMoteID - <id>2</id> - </interface_config> - <motetype_identifier>server</motetype_identifier> - </mote> - <mote> - <breakpoints /> - <interface_config> - org.contikios.cooja.interfaces.Position - <x>77.97942851220571</x> - <y>67.86182390447284</y> - <z>0.0</z> - </interface_config> - <interface_config> - org.contikios.cooja.mspmote.interfaces.MspMoteID - <id>3</id> - </interface_config> - <motetype_identifier>client</motetype_identifier> - </mote> - </simulation> - <plugin> - org.contikios.cooja.plugins.SimControl - <width>259</width> - <z>3</z> - <height>179</height> - <location_x>2</location_x> - <location_y>1</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.Visualizer - <plugin_config> - <skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.AttributeVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.LEDVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.AddressVisualizerSkin</skin> - <viewport>2.092412892721766 0.0 0.0 2.092412892721766 34.70057915472623 -45.606066372444175</viewport> - </plugin_config> - <width>300</width> - <z>4</z> - <height>178</height> - <location_x>261</location_x> - <location_y>1</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.LogListener - <plugin_config> - <filter /> - <formatted_time /> - <coloring /> - </plugin_config> - <width>762</width> - <z>0</z> - <height>491</height> - <location_x>2</location_x> - <location_y>182</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.RadioLogger - <plugin_config> - <split>167</split> - <formatted_time /> - <showdups>false</showdups> - <hidenodests>false</hidenodests> - <analyzers name="6lowpan" /> - </plugin_config> - <width>560</width> - <z>1</z> - <height>492</height> - <location_x>764</location_x> - <location_y>181</location_y> - </plugin> - <plugin> - org.contikios.cooja.serialsocket.SerialSocketServer - <mote_arg>0</mote_arg> - <plugin_config> - <port>60001</port> - <bound>true</bound> - </plugin_config> - <width>362</width> - <z>2</z> - <height>116</height> - <location_x>561</location_x> - <location_y>1</location_y> - </plugin> -</simconf> - diff --git a/examples/coap/server-client.csc b/examples/coap/server-client.csc deleted file mode 100644 index a649d048ab3d795ca44f87dca72fe4342f0501b3..0000000000000000000000000000000000000000 --- a/examples/coap/server-client.csc +++ /dev/null @@ -1,231 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<simconf> - <project EXPORT="discard">[APPS_DIR]/mrm</project> - <project EXPORT="discard">[APPS_DIR]/mspsim</project> - <project EXPORT="discard">[APPS_DIR]/avrora</project> - <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> - <project EXPORT="discard">[APPS_DIR]/powertracker</project> - <simulation> - <title>REST with RPL router</title> - <speedlimit>1.0</speedlimit> - <randomseed>123456</randomseed> - <motedelay_us>1000000</motedelay_us> - <radiomedium> - org.contikios.cooja.radiomediums.UDGM - <transmitting_range>50.0</transmitting_range> - <interference_range>50.0</interference_range> - <success_ratio_tx>1.0</success_ratio_tx> - <success_ratio_rx>1.0</success_ratio_rx> - </radiomedium> - <events> - <logoutput>40000</logoutput> - </events> - <motetype> - org.contikios.cooja.mspmote.SkyMoteType - <identifier>rplroot</identifier> - <description>Sky RPL Root</description> - <source EXPORT="discard">[CONTIKI_DIR]/examples/rpl-border-router/border-router.c</source> - <commands EXPORT="discard">make border-router.sky TARGET=sky</commands> - <firmware EXPORT="copy">[CONTIKI_DIR]/examples/rpl-border-router/border-router.sky</firmware> - <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface> - </motetype> - <motetype> - org.contikios.cooja.mspmote.SkyMoteType - <identifier>server</identifier> - <description>Erbium Server</description> - <source EXPORT="discard">[CONTIKI_DIR]/examples/coap/coap-example-server.c</source> - <commands EXPORT="discard">make coap-example-server.sky TARGET=sky</commands> - <firmware EXPORT="copy">[CONTIKI_DIR]/examples/coap/coap-example-server.sky</firmware> - <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface> - </motetype> - <motetype> - org.contikios.cooja.mspmote.SkyMoteType - <identifier>client</identifier> - <description>Erbium Client</description> - <source EXPORT="discard">[CONTIKI_DIR]/examples/coap/coap-example-client.c</source> - <commands EXPORT="discard">make coap-example-client.sky TARGET=sky</commands> - <firmware EXPORT="copy">[CONTIKI_DIR]/examples/coap/coap-example-client.sky</firmware> - <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface> - <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface> - </motetype> - <mote> - <breakpoints /> - <interface_config> - org.contikios.cooja.interfaces.Position - <x>33.260163187353555</x> - <y>30.643217359962595</y> - <z>0.0</z> - </interface_config> - <interface_config> - org.contikios.cooja.mspmote.interfaces.MspMoteID - <id>1</id> - </interface_config> - <motetype_identifier>rplroot</motetype_identifier> - </mote> - <mote> - <breakpoints /> - <interface_config> - org.contikios.cooja.interfaces.Position - <x>46.57186415376375</x> - <y>40.35946215910942</y> - <z>0.0</z> - </interface_config> - <interface_config> - org.contikios.cooja.mspmote.interfaces.MspMoteID - <id>2</id> - </interface_config> - <motetype_identifier>server</motetype_identifier> - </mote> - <mote> - <breakpoints /> - <interface_config> - org.contikios.cooja.interfaces.Position - <x>18.638049428485125</x> - <y>47.55034515769599</y> - <z>0.0</z> - </interface_config> - <interface_config> - org.contikios.cooja.mspmote.interfaces.MspMoteID - <id>3</id> - </interface_config> - <motetype_identifier>client</motetype_identifier> - </mote> - </simulation> - <plugin> - org.contikios.cooja.plugins.SimControl - <width>259</width> - <z>0</z> - <height>179</height> - <location_x>2</location_x> - <location_y>1</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.Visualizer - <plugin_config> - <skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.AttributeVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.LEDVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.AddressVisualizerSkin</skin> - <viewport>3.61568947862321 0.0 0.0 3.61568947862321 15.610600779367 -85.92728269158351</viewport> - </plugin_config> - <width>300</width> - <z>2</z> - <height>178</height> - <location_x>261</location_x> - <location_y>1</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.LogListener - <plugin_config> - <filter /> - <formatted_time /> - <coloring /> - </plugin_config> - <width>762</width> - <z>3</z> - <height>491</height> - <location_x>2</location_x> - <location_y>182</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.RadioLogger - <plugin_config> - <split>150</split> - <formatted_time /> - <showdups>false</showdups> - <hidenodests>false</hidenodests> - <analyzers name="6lowpan" /> - </plugin_config> - <width>451</width> - <z>-1</z> - <height>305</height> - <location_x>73</location_x> - <location_y>140</location_y> - <minimized>true</minimized> - </plugin> - <plugin> - org.contikios.cooja.serialsocket.SerialSocketServer - <mote_arg>0</mote_arg> - <width>422</width> - <z>4</z> - <height>74</height> - <location_x>578</location_x> - <location_y>18</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.TimeLine - <plugin_config> - <mote>0</mote> - <mote>1</mote> - <mote>2</mote> - <showRadioRXTX /> - <showRadioHW /> - <showLEDs /> - <showWatchpoints /> - <zoomfactor>25.49079397896416</zoomfactor> - </plugin_config> - <width>1624</width> - <z>5</z> - <height>252</height> - <location_x>6</location_x> - <location_y>712</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.MoteInterfaceViewer - <mote_arg>2</mote_arg> - <plugin_config> - <interface>Serial port</interface> - <scrollpos>0,0</scrollpos> - </plugin_config> - <width>853</width> - <z>1</z> - <height>491</height> - <location_x>765</location_x> - <location_y>182</location_y> - </plugin> -</simconf> - diff --git a/examples/dev/button-hal/Makefile b/examples/dev/button-hal/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..0c209918c336ac7fd404cfcd622bf12d59081324 --- /dev/null +++ b/examples/dev/button-hal/Makefile @@ -0,0 +1,8 @@ +CONTIKI_PROJECT = button-hal-example +CONTIKI = ../../.. + +all: $(CONTIKI_PROJECT) + +PLATFORMS_ONLY = srf06-cc26xx cc2538dk openmote-cc2538 zoul native + +include $(CONTIKI)/Makefile.include diff --git a/examples/dev/button-hal/README.md b/examples/dev/button-hal/README.md new file mode 100644 index 0000000000000000000000000000000000000000..d741ec73c9945c1ace778c5ea7f3e264e569188d --- /dev/null +++ b/examples/dev/button-hal/README.md @@ -0,0 +1,15 @@ +# Button HAL Example +This example demonstrates and tests the functionality of the Button HAL. +You can use this example to: + +* Understand the logic of the button HAL. +* Test your implementation of arch-specific button HAL components if you are +developing a new port. + +This example assumes a device with at least one switch (button or simiar). + +# Supported devices +This example is expected to work off-the-shelf on the following boards: + +* All CC13xx/CC26xx devices +* All CC2538 devices diff --git a/examples/dev/button-hal/button-hal-example.c b/examples/dev/button-hal/button-hal-example.c new file mode 100644 index 0000000000000000000000000000000000000000..db34b86af5627b7814367058aeb86ca1b91a9ea9 --- /dev/null +++ b/examples/dev/button-hal/button-hal-example.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/button-hal.h" + +#include <stdio.h> +/*---------------------------------------------------------------------------*/ +PROCESS(button_hal_example, "Button HAL Example"); +AUTOSTART_PROCESSES(&button_hal_example); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(button_hal_example, ev, data) +{ + button_hal_button_t *btn; + + PROCESS_BEGIN(); + + btn = button_hal_get_by_index(0); + + printf("Button HAL example.\n"); + printf("Device button count: %u.\n", button_hal_button_count); + + if(btn) { + printf("%s on pin %u with ID=0, Logic=%s, Pull=%s\n", + BUTTON_HAL_GET_DESCRIPTION(btn), btn->pin, + btn->negative_logic ? "Negative" : "Positive", + btn->pull == GPIO_HAL_PIN_CFG_PULL_UP ? "Pull Up" : "Pull Down"); + } + + while(1) { + + PROCESS_YIELD(); + + if(ev == button_hal_press_event) { + btn = (button_hal_button_t *)data; + printf("Press event (%s)\n", BUTTON_HAL_GET_DESCRIPTION(btn)); + + if(btn == button_hal_get_by_id(BUTTON_HAL_ID_BUTTON_ZERO)) { + printf("This was button 0, on pin %u\n", btn->pin); + } + } else if(ev == button_hal_release_event) { + btn = (button_hal_button_t *)data; + printf("Release event (%s)\n", BUTTON_HAL_GET_DESCRIPTION(btn)); + } else if(ev == button_hal_periodic_event) { + btn = (button_hal_button_t *)data; + printf("Periodic event, %u seconds (%s)\n", btn->press_duration_seconds, + BUTTON_HAL_GET_DESCRIPTION(btn)); + + if(btn->press_duration_seconds > 5) { + printf("%s pressed for more than 5 secs. Do custom action\n", + BUTTON_HAL_GET_DESCRIPTION(btn)); + } + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/dev/button-hal/project-conf.h b/examples/dev/button-hal/project-conf.h new file mode 100644 index 0000000000000000000000000000000000000000..457b42bfce57befe7eb4de99aaa13bfbc31b032f --- /dev/null +++ b/examples/dev/button-hal/project-conf.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ +/*---------------------------------------------------------------------------*/ +/* Force button descriptions */ +#define BUTTON_HAL_CONF_WITH_DESCRIPTION 1 +/*---------------------------------------------------------------------------*/ +#endif /* PROJECT_CONF_H_ */ +/*---------------------------------------------------------------------------*/ diff --git a/examples/dev/gpio-hal/Makefile b/examples/dev/gpio-hal/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..016f53377315d39dcd201b4099351ece23b7707b --- /dev/null +++ b/examples/dev/gpio-hal/Makefile @@ -0,0 +1,12 @@ +CONTIKI_PROJECT = gpio-hal-example +CONTIKI = ../../.. + +PLATFORMS_ONLY = srf06-cc26xx cc2538dk openmote-cc2538 zoul native + +include $(CONTIKI)/Makefile.identify-target + +MODULES_REL += $(TARGET) + +all: $(CONTIKI_PROJECT) + +include $(CONTIKI)/Makefile.include diff --git a/examples/dev/gpio-hal/README.md b/examples/dev/gpio-hal/README.md new file mode 100644 index 0000000000000000000000000000000000000000..84ab68f88372352da07eb060feb79519c23b0931 --- /dev/null +++ b/examples/dev/gpio-hal/README.md @@ -0,0 +1,36 @@ +# GPIO HAL Example +This example demonstrates and tests the functionality of the GPIO HAL. You can +use it to: + +* Understand the logic of the GPIO HAL. +* Test your implementation of arch-specific GPIO HAL components if you are +developing a new port. + +This example assumes a device with: + +* 3 output pins (e.g. LEDs). +* 1 button. + +# Supported devices +This example is expected to work off-the-shelf on the following boards: + +* All CC13xx/CC26xx devices +* All CC2538 devices + +# Extending for other platforms +Create a sub-directory with the same name as your platform. For example, for +platform `my-new-platform` create a subdirectory called `my-new-platform`. +Source files in this directory will be compiled automatically. In the most +simple case, all you will need is a source file called e.g. `pins.c` (it's OK +to use a different filename). In this file, you will need to provide +definitions of the variables used by the example to manipulate pins. These +variables are: + +* `out_pin1`, `out_pin2` and `out_pin3` for output pins. +* `btn_pin` for the button pin. + +Assign to those variables a value that corresponds to the output pin in your +board that you wish to test with the example. For example, if you have a LED +connected to pin 20, then you will need to + + gpio_hal_pin_t out_pin1 = 20; diff --git a/examples/dev/gpio-hal/cc2538dk/pins.c b/examples/dev/gpio-hal/cc2538dk/pins.c new file mode 100644 index 0000000000000000000000000000000000000000..4cb3e9742bff68eb2519caf2b734dcf0fdf20c26 --- /dev/null +++ b/examples/dev/gpio-hal/cc2538dk/pins.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +/*---------------------------------------------------------------------------*/ +/* + * LEDs on the SmartRF06 (EB and BB) are connected as follows: + * - LED1 (Red) -> PC0 + * - LED2 (Yellow) -> PC1 (gpio_hal_pin_t 17) + * - LED3 (Green) -> PC2 (gpio_hal_pin_t 18) + * - LED4 (Orange) -> PC3 (gpio_hal_pin_t 19) + * + * LED1 shares the same pin with the USB pullup, so here we'll use PC1, PC2 + * and PC3. + */ +gpio_hal_pin_t out_pin1 = 17; +gpio_hal_pin_t out_pin2 = 18; +gpio_hal_pin_t out_pin3 = 19; +/*---------------------------------------------------------------------------*/ +/* Button pin: Button select, PA3 */ +gpio_hal_pin_t btn_pin = 3; +/*---------------------------------------------------------------------------*/ diff --git a/examples/dev/gpio-hal/gpio-hal-example.c b/examples/dev/gpio-hal/gpio-hal-example.c new file mode 100644 index 0000000000000000000000000000000000000000..380c06388897e737127b0762cdc8ace42b33f2a1 --- /dev/null +++ b/examples/dev/gpio-hal/gpio-hal-example.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +#include "sys/etimer.h" +#include "lib/sensors.h" +#include "dev/button-hal.h" + +#include <stdio.h> +#include <inttypes.h> +/*---------------------------------------------------------------------------*/ +extern gpio_hal_pin_t out_pin1, out_pin2, out_pin3; +extern gpio_hal_pin_t btn_pin; +/*---------------------------------------------------------------------------*/ +static struct etimer et; +static uint8_t counter; +/*---------------------------------------------------------------------------*/ +/* Print gpio_hal_pin_mask_t using the correct format */ +#if GPIO_HAL_PIN_COUNT > 32 +#define PIN_MASK_FMT PRIx64 +#else +#define PIN_MASK_FMT PRIx32 +#endif +/*---------------------------------------------------------------------------*/ +PROCESS(gpio_hal_example, "GPIO HAL Example"); +AUTOSTART_PROCESSES(&gpio_hal_example); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(gpio_hal_example, ev, data) +{ + PROCESS_BEGIN(); + + counter = 0; + + etimer_set(&et, CLOCK_SECOND); + + while(1) { + + PROCESS_YIELD(); + + if(ev == PROCESS_EVENT_TIMER && data == &et) { + if((counter & 7) == 0) { + /* Set output and test write, high */ + gpio_hal_arch_pin_set_output(out_pin1); + gpio_hal_arch_pin_set_output(out_pin2); + gpio_hal_arch_pin_set_output(out_pin3); + + gpio_hal_arch_write_pin(out_pin1, 1); + gpio_hal_arch_write_pins( + gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3), + gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3)); + } else if((counter & 7) == 1) { + /* Test write, low */ + gpio_hal_arch_write_pin(out_pin1, 0); + gpio_hal_arch_write_pins( + gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3), 0); + } else if((counter & 7) == 2) { + /* Test set */ + gpio_hal_arch_set_pin(out_pin1); + gpio_hal_arch_set_pins( + gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3)); + } else if((counter & 7) == 3) { + /* Test clear */ + gpio_hal_arch_clear_pin(out_pin1); + gpio_hal_arch_clear_pins( + gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3)); + } else if((counter & 7) == 4) { + /* Test toggle (should go high) */ + gpio_hal_arch_toggle_pin(out_pin1); + gpio_hal_arch_toggle_pins( + gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3)); + } else if((counter & 7) == 5) { + /* Test toggle (should go low) */ + gpio_hal_arch_toggle_pin(out_pin1); + gpio_hal_arch_toggle_pins( + gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3)); + } else if((counter & 7) == 6) { + /* Set to input and then set. Should stay off */ + gpio_hal_arch_pin_set_input(out_pin1); + gpio_hal_arch_pin_set_input(out_pin2); + gpio_hal_arch_pin_set_input(out_pin3); + gpio_hal_arch_set_pin(out_pin1); + gpio_hal_arch_set_pins( + gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3)); + } else if((counter & 7) == 7) { + /* Toggle button interrupt */ + gpio_hal_pin_cfg_t interrupt; + + interrupt = gpio_hal_arch_pin_cfg_get(btn_pin) & + GPIO_HAL_PIN_CFG_INT_ENABLE; + + if(interrupt == 0) { + printf("Enabling button interrupt\n"); + gpio_hal_arch_interrupt_enable(btn_pin); + } else { + printf("Disabling button interrupt\n"); + gpio_hal_arch_interrupt_disable(btn_pin); + } + } + + /* Test read */ + printf("%u: Pins are 1-%u, 2=%u, 3=%u, mask=0x%08" PIN_MASK_FMT "\n", + counter & 7, + gpio_hal_arch_read_pin(out_pin1), + gpio_hal_arch_read_pin(out_pin2), + gpio_hal_arch_read_pin(out_pin3), + gpio_hal_arch_read_pins(gpio_hal_pin_to_mask(out_pin1) | + gpio_hal_pin_to_mask(out_pin2) | + gpio_hal_pin_to_mask(out_pin3))); + + counter++; + etimer_set(&et, CLOCK_SECOND); + } else if(ev == button_hal_release_event) { + printf("Button release event %s\n", + BUTTON_HAL_GET_DESCRIPTION((button_hal_button_t *)data)); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/dev/gpio-hal/native/pins.c b/examples/dev/gpio-hal/native/pins.c new file mode 100644 index 0000000000000000000000000000000000000000..10472b78a673334fdc0db4c39753df04cbaa5cf4 --- /dev/null +++ b/examples/dev/gpio-hal/native/pins.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_t out_pin1 = 0; +gpio_hal_pin_t out_pin2 = 1; +gpio_hal_pin_t out_pin3 = 2; +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_t btn_pin = 4; +/*---------------------------------------------------------------------------*/ diff --git a/examples/dev/gpio-hal/openmote-cc2538/pins.c b/examples/dev/gpio-hal/openmote-cc2538/pins.c new file mode 100644 index 0000000000000000000000000000000000000000..340aff15c5b65ff0bcdebb036187f975e45a854a --- /dev/null +++ b/examples/dev/gpio-hal/openmote-cc2538/pins.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +/*---------------------------------------------------------------------------*/ +/* + * LEDs on the OpenMote-CC2538 are connected as follows: + * - LED1 (Red) -> PC4 (gpio_hal_pin_t 20) + * - LED2 (Yellow) -> PC6 (gpio_hal_pin_t 22) + * - LED3 (Green) -> PC7 (gpio_hal_pin_t 23) + * - LED4 (Orange) -> PC5 + */ +gpio_hal_pin_t out_pin1 = 20; +gpio_hal_pin_t out_pin2 = 22; +gpio_hal_pin_t out_pin3 = 23; +/*---------------------------------------------------------------------------*/ +/* Button pin: PC3 */ +gpio_hal_pin_t btn_pin = 19; +/*---------------------------------------------------------------------------*/ diff --git a/examples/dev/gpio-hal/srf06-cc26xx/pins.c b/examples/dev/gpio-hal/srf06-cc26xx/pins.c new file mode 100644 index 0000000000000000000000000000000000000000..700f8961be99856d2c7e1a6ebb06bbe06a2a5532 --- /dev/null +++ b/examples/dev/gpio-hal/srf06-cc26xx/pins.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +/*---------------------------------------------------------------------------*/ +#if CONTIKI_BOARD_SENSORTAG_CC1350 +#define PINS2_AND_3 BOARD_IOID_LED_1 +#else +#define PINS2_AND_3 BOARD_IOID_LED_2 +#endif +gpio_hal_pin_t out_pin1 = BOARD_IOID_LED_1; +gpio_hal_pin_t out_pin2 = PINS2_AND_3; +gpio_hal_pin_t out_pin3 = PINS2_AND_3; +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_t btn_pin = BOARD_IOID_KEY_LEFT; +/*---------------------------------------------------------------------------*/ diff --git a/examples/dev/gpio-hal/zoul/pins.c b/examples/dev/gpio-hal/zoul/pins.c new file mode 100644 index 0000000000000000000000000000000000000000..ff44bf4d1173be8e2250cb832572d9cf9086b7f3 --- /dev/null +++ b/examples/dev/gpio-hal/zoul/pins.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_t out_pin1 = (LEDS_ARCH_L1_PORT << 3) + LEDS_ARCH_L1_PIN; +gpio_hal_pin_t out_pin2 = (LEDS_ARCH_L2_PORT << 3) + LEDS_ARCH_L2_PIN; +gpio_hal_pin_t out_pin3 = (LEDS_ARCH_L3_PORT << 3) + LEDS_ARCH_L3_PIN; +/*---------------------------------------------------------------------------*/ +gpio_hal_pin_t btn_pin = (BUTTON_USER_PORT << 3) + BUTTON_USER_PIN; +/*---------------------------------------------------------------------------*/ diff --git a/examples/dev/leds/Makefile b/examples/dev/leds/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..7c5f5f59283ffc40cde80a41c9ee15275342fd99 --- /dev/null +++ b/examples/dev/leds/Makefile @@ -0,0 +1,8 @@ +CONTIKI_PROJECT = leds-example +CONTIKI = ../../.. + +MODULES_REL += $(TARGET) + +all: $(CONTIKI_PROJECT) + +include $(CONTIKI)/Makefile.include diff --git a/examples/dev/leds/README.md b/examples/dev/leds/README.md new file mode 100644 index 0000000000000000000000000000000000000000..05bdc20bab7dc99e08fd5ced50fd2574e0e87edc --- /dev/null +++ b/examples/dev/leds/README.md @@ -0,0 +1,15 @@ +# LED HAL Example +This example demonstrates and tests the functionality of the LED HAL. You can +use it to: + +* Understand the logic of the LED HAL. +* Test your implementation of arch-specific LED HAL components if you are +developing a new port. + +This example assumes a device with at least 1 LED. + +# Supported devices +This example is expected to work off-the-shelf on the following boards: + +* All CC13xx/CC26xx devices +* All CC2538 devices diff --git a/examples/dev/leds/leds-example.c b/examples/dev/leds/leds-example.c new file mode 100644 index 0000000000000000000000000000000000000000..b62668e8b9cfc16f43340037a16d14a309294606 --- /dev/null +++ b/examples/dev/leds/leds-example.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/leds.h" +#include "sys/etimer.h" + +#include <stdio.h> +/*---------------------------------------------------------------------------*/ +static struct etimer et; +static uint8_t counter; +/*---------------------------------------------------------------------------*/ +PROCESS(leds_example, "LED HAL Example"); +AUTOSTART_PROCESSES(&leds_example); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(leds_example, ev, data) +{ + PROCESS_BEGIN(); + + counter = 0; + + etimer_set(&et, CLOCK_SECOND); + + while(1) { + + PROCESS_YIELD(); + + if(ev == PROCESS_EVENT_TIMER && data == &et) { + if((counter & 7) == 0) { + leds_set(LEDS_ALL); + } else if((counter & 7) == 1) { + leds_off(LEDS_ALL); + } else if((counter & 7) == 2) { + leds_on(LEDS_ALL); + } else if((counter & 7) == 3) { + leds_toggle(LEDS_ALL); +#if !LEDS_LEGACY_API + } else if((counter & 7) == 4) { + leds_single_on(LEDS_LED1); + } else if((counter & 7) == 5) { + leds_single_off(LEDS_LED1); + } else if((counter & 7) == 6) { + leds_single_toggle(LEDS_LED1); +#endif /* LEDS_LEGACY_API */ + } else if((counter & 7) == 7) { + leds_toggle(LEDS_ALL); + } + + counter++; + etimer_set(&et, CLOCK_SECOND); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/dev/rgb-led/Makefile b/examples/dev/rgb-led/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e2142cf2d3eadb0f54c2222bc17e46c470062b6f --- /dev/null +++ b/examples/dev/rgb-led/Makefile @@ -0,0 +1,10 @@ +CONTIKI_PROJECT = rgb-led-example +CONTIKI = ../../.. + +MODULES_REL += $(TARGET) + +PLATFORMS_ONLY = zoul + +all: $(CONTIKI_PROJECT) + +include $(CONTIKI)/Makefile.include diff --git a/examples/dev/rgb-led/Makefile.target b/examples/dev/rgb-led/Makefile.target new file mode 100644 index 0000000000000000000000000000000000000000..75430a6e4228757cd766c5497c24bc42c3d57c30 --- /dev/null +++ b/examples/dev/rgb-led/Makefile.target @@ -0,0 +1 @@ +TARGET = zoul diff --git a/examples/dev/rgb-led/README.md b/examples/dev/rgb-led/README.md new file mode 100644 index 0000000000000000000000000000000000000000..1b10926ce8dde4784a96f5f4cfac5f77cedac447 --- /dev/null +++ b/examples/dev/rgb-led/README.md @@ -0,0 +1,14 @@ +# RGB LED Example +This example demonstrates and tests the functionality of the RGB LED driver. +You can use it to: + +* Understand the logic of the RGB LED driver. +* Test your implementation if you are developing a new port for a device that +features this part. + +This example assumes a device with an RGB LED. + +# Supported devices +This example is expected to work off-the-shelf on the following boards: + +* All Zoul-based devices diff --git a/examples/dev/rgb-led/rgb-led-example.c b/examples/dev/rgb-led/rgb-led-example.c new file mode 100644 index 0000000000000000000000000000000000000000..e2c2de21ee54002fb39410e6dffcb1c184875982 --- /dev/null +++ b/examples/dev/rgb-led/rgb-led-example.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/rgb-led/rgb-led.h" +#include "sys/etimer.h" + +#include <stdio.h> +/*---------------------------------------------------------------------------*/ +static struct etimer et; +static uint8_t counter; +/*---------------------------------------------------------------------------*/ +PROCESS(rgb_led_example, "RGB LED Example"); +AUTOSTART_PROCESSES(&rgb_led_example); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(rgb_led_example, ev, data) +{ + PROCESS_BEGIN(); + + counter = 0; + + etimer_set(&et, CLOCK_SECOND); + + while(1) { + + PROCESS_YIELD(); + + if(ev == PROCESS_EVENT_TIMER && data == &et) { + if((counter & 7) == 0) { + rgb_led_off(); + } else if((counter & 7) == 1) { + rgb_led_set(RGB_LED_RED); + } else if((counter & 7) == 2) { + rgb_led_set(RGB_LED_GREEN); + } else if((counter & 7) == 3) { + rgb_led_set(RGB_LED_BLUE); + } else if((counter & 7) == 4) { + rgb_led_set(RGB_LED_CYAN); + } else if((counter & 7) == 5) { + rgb_led_set(RGB_LED_MAGENTA); + } else if((counter & 7) == 6) { + rgb_led_set(RGB_LED_YELLOW); + } else if((counter & 7) == 7) { + rgb_led_set(RGB_LED_WHITE); + } + + counter++; + etimer_set(&et, CLOCK_SECOND); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/hello-world/hello-world.c b/examples/hello-world/hello-world.c index 30724140e1e22e6b256cbcd267f9de5323d4ee46..e6d452d9e760ea90f77f611ddb64bb007f46d2ed 100644 --- a/examples/hello-world/hello-world.c +++ b/examples/hello-world/hello-world.c @@ -46,10 +46,21 @@ AUTOSTART_PROCESSES(&hello_world_process); /*---------------------------------------------------------------------------*/ PROCESS_THREAD(hello_world_process, ev, data) { + static struct etimer timer; + PROCESS_BEGIN(); - printf("Hello, world\n"); - + /* Setup a periodic timer that expires after 10 seconds. */ + etimer_set(&timer, CLOCK_SECOND * 10); + + while(1) { + printf("Hello, world\n"); + + /* Wait for the periodic timer to expire and then restart the timer. */ + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer)); + etimer_reset(&timer); + } + PROCESS_END(); } /*---------------------------------------------------------------------------*/ diff --git a/examples/http-socket/Makefile b/examples/http-socket/Makefile deleted file mode 100644 index e1904d3abc30215e804a17384938ffea48412dd7..0000000000000000000000000000000000000000 --- a/examples/http-socket/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -all: http-example websocket-example -CONTIKI=../.. -MODULES += os/net/app-layer/http-socket - -include $(CONTIKI)/Makefile.include diff --git a/examples/http-socket/websocket-node/Makefile b/examples/http-socket/websocket-node/Makefile deleted file mode 100644 index cde795492d5cf479b116a4e39cdc08cadc24052b..0000000000000000000000000000000000000000 --- a/examples/http-socket/websocket-node/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -install: - npm install websocket - - -run: - nodejs example-server.js diff --git a/examples/ip64-router/Makefile b/examples/ip64-router/Makefile index a77652cfacdee0c4bcaa913c8ffe6f83e3677813..0beea11bd485277491cbb25d8e5b2c7ca40e2cf1 100644 --- a/examples/ip64-router/Makefile +++ b/examples/ip64-router/Makefile @@ -1,4 +1,11 @@ -all: ip64-router +CONTIKI_PROJECT = ip64-router +all: $(CONTIKI_PROJECT) CONTIKI=../.. +# Currently only supported on Orion, the only platform with 802.15.4 + Ethernet +PLATFORMS_ONLY = zoul +BOARDS_ONLY = orion +BOARD = orion +WITH_IP64 = 1 + include $(CONTIKI)/Makefile.include diff --git a/examples/ip64-router/ip64-router.c b/examples/ip64-router/ip64-router.c index a6a5af45088f8a51e8b83c885efdf6ab4da9c141..632b9ba2e5de88654ba037244e407c012ea7668b 100644 --- a/examples/ip64-router/ip64-router.c +++ b/examples/ip64-router/ip64-router.c @@ -2,7 +2,7 @@ #include "contiki-net.h" #include "ip64/ip64.h" #include "net/netstack.h" -#include "rpl-dag-root.h" +#include "net/routing/routing.h" #include "sys/autostart.h" /*---------------------------------------------------------------------------*/ @@ -14,7 +14,7 @@ PROCESS_THREAD(router_node_process, ev, data) PROCESS_BEGIN(); /* Set us up as a RPL root node. */ - rpl_dag_root_init_dag_delay(); + NETSTACK_ROUTING.root_start(); /* Initialize the IP64 module so we'll start translating packets */ ip64_init(); diff --git a/examples/ipso-objects/Makefile b/examples/ipso-objects/Makefile deleted file mode 100644 index d4a1ef50339e9606c75ccc2ec72f57c4cad7de4b..0000000000000000000000000000000000000000 --- a/examples/ipso-objects/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -CONTIKI_PROJECT = example-ipso-objects - -CONTIKI_SOURCEFILES += serial-protocol.c example-ipso-temperature.c - -all: $(CONTIKI_PROJECT) - -MODULES += os/net/app-layer/coap -MODULES += os/services/lwm2m -MODULES += os/services/ipso-objects - -CONTIKI=../.. -include $(CONTIKI)/Makefile.include - -# border router rules -$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c - (cd $(CONTIKI)/tools && $(MAKE) tunslip6) - -connect-router: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 aaaa::1/64 - -connect-router-cooja: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 -p 60001 aaaa::1/64 - -connect-router-native: $(CONTIKI)/examples/native-border-router/border-router.native - sudo $(CONTIKI)/examples/native-border-router/border-router.native -a 127.0.0.1 -p 60001 aaaa::1/64 diff --git a/examples/ipso-objects/README.md b/examples/ipso-objects/README.md deleted file mode 100644 index e9be82dcb6f6c08e72479de1929c9574888ddf78..0000000000000000000000000000000000000000 --- a/examples/ipso-objects/README.md +++ /dev/null @@ -1,48 +0,0 @@ -IPSO Objects Example -============================================ - -This is an example of how to make use of the IPSO Object and LWM2M -implementation in Contiki. - -The LWM2M implementation is based on the Erbium CoAP implementation -and consists of two apps: lwm2m-engine and ipso-objects. The -lwm2m-engine handle the specifics of LWM2M including bootstrapping and -how read/writes of objects and resources are handled. The ipso-objects -contains implementations of some of the IPSO Smart Objects. - -The implementation was used during the IPSO Interop in May 2015, -Kista, Sweden, and was successfully tested with other -implementations. - -The examples use some of the basic IPSO object for controlling LEDs on -Contiki devices and for reading out temperature. - -##Testing IPSO-objects with Leshan - -First program a device with the examples/ipso-objects/example-ipso-objects.c - -```bash ->make example-ipso-objects.upload TARGET=zoul ->... -``` - -After that start up a native-border router or other border router on fd00::1/64 -or another prefix - NOTE: if you use another prefix you will need to change LWM2M_SERVER_ADDRESS for which the device will register - in project-conf.h: -``` -#define LWM2M_SERVER_ADDRESS "fd00::1" -``` - -Then when everything is setup you can download a Leshan and use that to -test controlling LEDs of the device. - -###Starting Leshan -```bash -wget https://hudson.eclipse.org/leshan/job/leshan/lastSuccessfulBuild/artifact/leshan-standalone.jar -java -jar ./leshan-standalone.jar -``` -Browse to leshans device page with http://127.0.0.1:8080 . - -When you have started the border-router and also Leshan you should now -start (or reboot) your IPSO Object enabled device. Within 30 seconds -you should be able to see it on the Leshan device page. - diff --git a/examples/ipso-objects/example-ipso-objects.c b/examples/ipso-objects/example-ipso-objects.c deleted file mode 100644 index 18036907628feb38db4d9365fb0aa8154cc5304c..0000000000000000000000000000000000000000 --- a/examples/ipso-objects/example-ipso-objects.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2015, Yanzi Networks AB. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -/** - * \file - * OMA LWM2M and IPSO Objects example. - * \author - * Joakim Eriksson, joakime@sics.se - * Niclas Finne, nfi@sics.se - */ - -#include "contiki.h" -#include "services/lwm2m/lwm2m-engine.h" -#include "services/ipso-objects/ipso-objects.h" - -#define DEBUG DEBUG_NONE -#include "net/ipv6/uip-debug.h" - -#ifndef REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER -#define REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER 0 -#endif - -#ifndef REGISTER_WITH_LWM2M_SERVER -#define REGISTER_WITH_LWM2M_SERVER 1 -#endif - -#ifndef LWM2M_SERVER_ADDRESS -#define LWM2M_SERVER_ADDRESS "fd00::1" -#endif - -PROCESS(example_ipso_objects, "IPSO object example"); -AUTOSTART_PROCESSES(&example_ipso_objects); -/*---------------------------------------------------------------------------*/ -static void -setup_lwm2m_servers(void) -{ -#ifdef LWM2M_SERVER_ADDRESS - uip_ipaddr_t addr; - if(uiplib_ipaddrconv(LWM2M_SERVER_ADDRESS, &addr)) { - lwm2m_engine_register_with_bootstrap_server(&addr, 0); - lwm2m_engine_register_with_server(&addr, 0); - } -#endif /* LWM2M_SERVER_ADDRESS */ - - lwm2m_engine_use_bootstrap_server(REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER); - lwm2m_engine_use_registration_server(REGISTER_WITH_LWM2M_SERVER); -} -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(example_ipso_objects, ev, data) -{ - PROCESS_BEGIN(); - - PROCESS_PAUSE(); - - PRINTF("Starting IPSO objects example\n"); - - /* Initialize the OMA LWM2M engine */ - lwm2m_engine_init(); - - /* Register default LWM2M objects */ - lwm2m_engine_register_default_objects(); - - /* Register default IPSO objects */ - ipso_objects_init(); - - setup_lwm2m_servers(); - - while(1) { - PROCESS_WAIT_EVENT(); - } - - PROCESS_END(); -} diff --git a/examples/ipv6-hooks/Makefile b/examples/ipv6-hooks/Makefile deleted file mode 100644 index bbd4b716883ce6a2fd0365bdd922a5cbbff65a39..0000000000000000000000000000000000000000 --- a/examples/ipv6-hooks/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -all: ipv6-hooks - -CONTIKI=../.. -include $(CONTIKI)/Makefile.include diff --git a/examples/libs/data-structures/Makefile b/examples/libs/data-structures/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1f4d6b765afaf9c64f7d7cf1c11d97374ef60b12 --- /dev/null +++ b/examples/libs/data-structures/Makefile @@ -0,0 +1,7 @@ +CONTIKI_PROJECT = data-structures + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. + +include $(CONTIKI)/Makefile.include diff --git a/examples/libs/data-structures/data-structures.c b/examples/libs/data-structures/data-structures.c new file mode 100644 index 0000000000000000000000000000000000000000..21752762aa2f1ee85cef11c8a6e91298ee6d1985 --- /dev/null +++ b/examples/libs/data-structures/data-structures.c @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * Copyright (c) 2017, James Pope + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/stack.h" +#include "lib/queue.h" +#include "lib/circular-list.h" +#include "lib/dbl-list.h" +#include "lib/dbl-circ-list.h" +#include "lib/random.h" + +#include <string.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +/*---------------------------------------------------------------------------*/ +PROCESS(data_structure_process, "Data structure process"); +AUTOSTART_PROCESSES(&data_structure_process); +/*---------------------------------------------------------------------------*/ +STACK(demo_stack); +QUEUE(demo_queue); +CIRCULAR_LIST(demo_cll); +DBL_LIST(demo_dbl); +DBL_CIRC_LIST(demo_dblcl); +/*---------------------------------------------------------------------------*/ +typedef struct demo_struct_s { + struct demo_struct_s *next; + struct demo_struct_s *previous; + unsigned short value; +} demo_struct_t; +/*---------------------------------------------------------------------------*/ +#define DATA_STRUCTURE_DEMO_ELEMENT_COUNT 4 +static demo_struct_t elements[DATA_STRUCTURE_DEMO_ELEMENT_COUNT]; +/*---------------------------------------------------------------------------*/ +static void +dbl_circ_list_print(dbl_circ_list_t dblcl) +{ + demo_struct_t *this = *dblcl; + + if(*dblcl == NULL) { + printf("Length=0\n"); + return; + } + + do { + printf("<--(0x%04x)--0x%04x--(0x%04x)-->", this->previous->value, + this->value, this->next->value); + this = this->next; + } while(this != *dblcl); + + printf(" (Length=%lu)\n", dbl_circ_list_length(dblcl)); +} +/*---------------------------------------------------------------------------*/ +static void +demonstrate_dbl_circ_list(void) +{ + int i; + demo_struct_t *this; + + dbl_circ_list_init(demo_dblcl); + printf("============================\n"); + printf("Circular, doubly-linked list\n"); + + for(i = 0; i < DATA_STRUCTURE_DEMO_ELEMENT_COUNT; i++) { + elements[i].next = NULL; + elements[i].previous = NULL; + } + + /* Add elements */ + dbl_circ_list_add_tail(demo_dblcl, &elements[0]); + printf("Add tail : 0x%04x | ", elements[0].value); + dbl_circ_list_print(demo_dblcl); + + dbl_circ_list_add_after(demo_dblcl, &elements[0], &elements[1]); + printf("Add after : 0x%04x | ", elements[1].value); + dbl_circ_list_print(demo_dblcl); + + dbl_circ_list_add_head(demo_dblcl, &elements[2]); + printf("Add head : 0x%04x | ", elements[2].value); + dbl_circ_list_print(demo_dblcl); + + dbl_circ_list_add_before(demo_dblcl, &elements[2], &elements[3]); + printf("Add before: 0x%04x | ", elements[3].value); + dbl_circ_list_print(demo_dblcl); + + /* Remove head */ + this = dbl_circ_list_head(demo_dblcl); + printf("Rm head: (0x%04x) | ", this->value); + dbl_circ_list_remove(demo_dblcl, this); + dbl_circ_list_print(demo_dblcl); + + /* Remove currently second element */ + this = ((demo_struct_t *)dbl_circ_list_head(demo_dblcl))->next; + printf("Rm 2nd : (0x%04x) | ", this->value); + dbl_circ_list_remove(demo_dblcl, this); + dbl_circ_list_print(demo_dblcl); + + /* Remove tail */ + this = dbl_circ_list_tail(demo_dblcl); + printf("Rm tail: (0x%04x) | ", this->value); + dbl_circ_list_remove(demo_dblcl, this); + dbl_circ_list_print(demo_dblcl); + + /* Remove last remaining element */ + this = dbl_circ_list_tail(demo_dblcl); + printf("Rm last: (0x%04x) | ", this->value); + dbl_circ_list_remove(demo_dblcl, this); + dbl_circ_list_print(demo_dblcl); + + printf("Circular, doubly-linked list is%s empty\n", + dbl_circ_list_is_empty(demo_dblcl) ? "" : " not"); +} +/*---------------------------------------------------------------------------*/ +static void +dbl_list_print(dbl_list_t dll) +{ + demo_struct_t *this; + + for(this = *dll; this != NULL; this = this->next) { + printf("<--("); + if(this->previous == NULL) { + printf(" null "); + } else { + printf("0x%04x", this->previous->value); + } + + printf(")--0x%04x--(", this->value); + + if(this->next == NULL) { + printf(" null "); + } else { + printf("0x%04x", this->next->value); + } + printf(")-->"); + } + + printf(" (Length=%lu)\n", dbl_list_length(dll)); +} +/*---------------------------------------------------------------------------*/ +static void +demonstrate_dbl_list(void) +{ + int i; + demo_struct_t *this; + + dbl_list_init(demo_dbl); + printf("==================\n"); + printf("Doubly-linked list\n"); + + for(i = 0; i < DATA_STRUCTURE_DEMO_ELEMENT_COUNT; i++) { + elements[i].next = NULL; + elements[i].previous = NULL; + } + + /* Add elements */ + dbl_list_add_tail(demo_dbl, &elements[0]); + printf("Add tail : 0x%04x | ", elements[0].value); + dbl_list_print(demo_dbl); + + dbl_list_add_after(demo_dbl, &elements[0], &elements[1]); + printf("Add after : 0x%04x | ", elements[1].value); + dbl_list_print(demo_dbl); + + dbl_list_add_head(demo_dbl, &elements[2]); + printf("Add head : 0x%04x | ", elements[2].value); + dbl_list_print(demo_dbl); + + dbl_list_add_before(demo_dbl, &elements[2], &elements[3]); + printf("Add before: 0x%04x | ", elements[3].value); + dbl_list_print(demo_dbl); + + /* Remove head */ + this = dbl_list_head(demo_dbl); + printf("Rm head: (0x%04x) | ", this->value); + dbl_list_remove(demo_dbl, this); + dbl_list_print(demo_dbl); + + /* Remove currently second element */ + this = ((demo_struct_t *)dbl_list_head(demo_dbl))->next; + printf("Rm 2nd : (0x%04x) | ", this->value); + dbl_list_remove(demo_dbl, this); + dbl_list_print(demo_dbl); + + /* Remove tail */ + this = dbl_list_tail(demo_dbl); + printf("Rm tail: (0x%04x) | ", this->value); + dbl_list_remove(demo_dbl, this); + dbl_list_print(demo_dbl); + + /* Remove last remaining element */ + this = dbl_list_tail(demo_dbl); + printf("Rm last: (0x%04x) | ", this->value); + dbl_list_remove(demo_dbl, this); + dbl_list_print(demo_dbl); + + printf("Doubly-linked list is%s empty\n", + dbl_list_is_empty(demo_dbl) ? "" : " not"); +} +/*---------------------------------------------------------------------------*/ +static void +circular_list_print(circular_list_t cl) +{ + demo_struct_t *this = *cl; + + if(*cl == NULL) { + printf("Length=0\n"); + return; + } + + do { + printf("0x%04x-->", this->value); + this = this->next; + } while(this != *cl); + + printf("0x%04x (Length=%lu)\n", this->value, circular_list_length(cl)); +} +/*---------------------------------------------------------------------------*/ +static void +demonstrate_circular_list(void) +{ + int i; + + circular_list_init(demo_cll); + printf("============================\n"); + printf("Circular, singly-linked list\n"); + + /* Add elements */ + for(i = 0; i < DATA_STRUCTURE_DEMO_ELEMENT_COUNT; i++) { + elements[i].next = NULL; + circular_list_add(demo_cll, &elements[i]); + + printf("Add: 0x%04x | ", elements[i].value); + circular_list_print(demo_cll); + } + + /* Remove head */ + circular_list_remove(demo_cll, circular_list_head(demo_cll)); + printf("Remove head | "); + circular_list_print(demo_cll); + + /* Remove currently second element */ + circular_list_remove(demo_cll, + ((demo_struct_t *)circular_list_head(demo_cll))->next); + printf("Remove 2nd | "); + circular_list_print(demo_cll); + + /* Remove tail */ + circular_list_remove(demo_cll, circular_list_tail(demo_cll)); + printf("Remove tail | "); + circular_list_print(demo_cll); + + /* Remove last remaining element */ + circular_list_remove(demo_cll, circular_list_tail(demo_cll)); + printf("Remove last | "); + circular_list_print(demo_cll); + + printf("Circular list is%s empty\n", + circular_list_is_empty(demo_cll) ? "" : " not"); +} +/*---------------------------------------------------------------------------*/ +static void +demonstrate_stack(void) +{ + int i; + demo_struct_t *this; + + printf("=====\n"); + printf("Stack\n"); + + stack_init(demo_stack); + + /* Add elements */ + for(i = 0; i < DATA_STRUCTURE_DEMO_ELEMENT_COUNT; i++) { + elements[i].next = NULL; + stack_push(demo_stack, &elements[i]); + printf("Push: 0x%04x\n", elements[i].value); + } + + printf("Peek: 0x%04x\n", + ((demo_struct_t *)stack_peek(demo_stack))->value); + + for(i = 0; i <= DATA_STRUCTURE_DEMO_ELEMENT_COUNT; i++) { + this = stack_pop(demo_stack); + printf("Pop: "); + if(this == NULL) { + printf("(stack underflow)\n"); + } else { + printf("0x%04x\n", this->value); + } + } + printf("Stack is%s empty\n", + stack_is_empty(demo_stack) ? "" : " not"); +} +/*---------------------------------------------------------------------------*/ +static void +demonstrate_queue(void) +{ + int i; + demo_struct_t *this; + + printf("=====\n"); + printf("Queue\n"); + + queue_init(demo_queue); + + /* Add elements */ + for(i = 0; i < DATA_STRUCTURE_DEMO_ELEMENT_COUNT; i++) { + elements[i].next = NULL; + queue_enqueue(demo_queue, &elements[i]); + printf("Enqueue: 0x%04x\n", elements[i].value); + } + + printf("Peek: 0x%04x\n", + ((demo_struct_t *)queue_peek(demo_queue))->value); + + for(i = 0; i <= DATA_STRUCTURE_DEMO_ELEMENT_COUNT; i++) { + this = queue_dequeue(demo_queue); + printf("Dequeue: "); + if(this == NULL) { + printf("(queue underflow)\n"); + } else { + printf("0x%04lx\n", (unsigned long)this->value); + } + } + + printf("Queue is%s empty\n", + queue_is_empty(demo_queue) ? "" : " not"); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(data_structure_process, ev, data) +{ + int i; + + PROCESS_BEGIN(); + + /* Generate some elements */ + printf("Elements: ["); + + for(i = 0; i < DATA_STRUCTURE_DEMO_ELEMENT_COUNT; i++) { + elements[i].next = NULL; + elements[i].value = random_rand(); + printf(" 0x%04x", elements[i].value); + } + printf(" ]\n"); + + demonstrate_stack(); + demonstrate_queue(); + demonstrate_circular_list(); + demonstrate_dbl_list(); + demonstrate_dbl_circ_list(); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/libs/ipv6-hooks/Makefile b/examples/libs/ipv6-hooks/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..63085face7b36e187cd9e22ca304dddc88ef9ed0 --- /dev/null +++ b/examples/libs/ipv6-hooks/Makefile @@ -0,0 +1,5 @@ +CONTIKI_PROJECT = ipv6-hooks +all: $(CONTIKI_PROJECT) + +CONTIKI=../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/ipv6-hooks/README.md b/examples/libs/ipv6-hooks/README.md similarity index 100% rename from examples/ipv6-hooks/README.md rename to examples/libs/ipv6-hooks/README.md diff --git a/examples/ipv6-hooks/ipv6-hooks.c b/examples/libs/ipv6-hooks/ipv6-hooks.c similarity index 96% rename from examples/ipv6-hooks/ipv6-hooks.c rename to examples/libs/ipv6-hooks/ipv6-hooks.c index 30269b030ff4374cae56879b35e384e4c7067391..d3ca8861c3954c266bcd36a0117adec23d42a1b0 100644 --- a/examples/ipv6-hooks/ipv6-hooks.c +++ b/examples/libs/ipv6-hooks/ipv6-hooks.c @@ -1,9 +1,10 @@ #include "contiki.h" -#include "rpl.h" +#include "net/routing/routing.h" #include "random.h" #include "net/netstack.h" #include "net/ipv6/simple-udp.h" #include "net/ipv6/uipbuf.h" +#include "net/ipv6/uip-ds6.h" #include "sys/log.h" #define LOG_MODULE "App" diff --git a/examples/libs/logging/Makefile b/examples/libs/logging/Makefile index d394c0bc4d48faef5b2795b0134a1988ddf36d37..eead5bc902611359e299008b6b8fb0c19c0b10bd 100644 --- a/examples/libs/logging/Makefile +++ b/examples/libs/logging/Makefile @@ -1,5 +1,8 @@ CONTIKI_PROJECT = logging all: $(CONTIKI_PROJECT) +# Does not fit on Sky +PLATFORMS_EXCLUDE = sky + CONTIKI = ../../.. include $(CONTIKI)/Makefile.include diff --git a/examples/libs/logging/project-conf.h b/examples/libs/logging/project-conf.h index f42f0872377b016f499d4fcb7a1125940444d68d..8f393c3196af0ec04c0311cacd6fe8f7785959c6 100644 --- a/examples/libs/logging/project-conf.h +++ b/examples/libs/logging/project-conf.h @@ -45,6 +45,8 @@ #define LOG_CONF_LEVEL_TCPIP LOG_LEVEL_DBG #define LOG_CONF_LEVEL_MAC LOG_LEVEL_DBG #define LOG_CONF_LEVEL_FRAMER LOG_LEVEL_DBG +#define LOG_CONF_LEVEL_COAP LOG_LEVEL_DBG +#define LOG_CONF_LEVEL_LWM2M LOG_LEVEL_DBG #define LOG_CONF_LEVEL_6TOP LOG_LEVEL_DBG /* Enable cooja annotations */ diff --git a/examples/libs/stack-check/Makefile b/examples/libs/stack-check/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..02b94cfc03e003edb1cb23b6a38e8e198bf43141 --- /dev/null +++ b/examples/libs/stack-check/Makefile @@ -0,0 +1,7 @@ +CONTIKI_PROJECT = example-stack-check +all: $(CONTIKI_PROJECT) + +PLATFORMS_EXCLUDE = native cooja + +CONTIKI = ../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/libs/stack-check/example-sky.csc b/examples/libs/stack-check/example-sky.csc new file mode 100644 index 0000000000000000000000000000000000000000..ae09f50bbc301e232f0664df7cfcf8028696af30 --- /dev/null +++ b/examples/libs/stack-check/example-sky.csc @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="UTF-8"?> +<simconf> + <project EXPORT="discard">[CONTIKI_DIR]/tools/cooja/apps/mrm</project> + <project EXPORT="discard">[CONTIKI_DIR]/tools/cooja/apps/mspsim</project> + <project EXPORT="discard">[CONTIKI_DIR]/tools/cooja/apps/avrora</project> + <project EXPORT="discard">[CONTIKI_DIR]/tools/cooja/apps/serial_socket</project> + <simulation> + <title>Stack checker example</title> + <delaytime>0</delaytime> + <randomseed>123456</randomseed> + <motedelay_us>1000000</motedelay_us> + <radiomedium> + org.contikios.cooja.radiomediums.UDGM + <transmitting_range>50.0</transmitting_range> + <interference_range>50.0</interference_range> + <success_ratio_tx>1.0</success_ratio_tx> + <success_ratio_rx>1.0</success_ratio_rx> + </radiomedium> + <events> + <logoutput>40000</logoutput> + </events> + <motetype> + org.contikios.cooja.mspmote.SkyMoteType + <identifier>node</identifier> + <description>RPL Root</description> + <source EXPORT="discard">[CONFIG_DIR]/example-stack-check.c</source> + <commands EXPORT="discard">make example-stack-check.sky TARGET=sky</commands> + <firmware EXPORT="copy">[CONFIG_DIR]/example-stack-check.sky</firmware> + <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface> + </motetype> + <mote> + <breakpoints /> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>33.260163187353555</x> + <y>30.643217359962595</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.mspmote.interfaces.MspMoteID + <id>1</id> + </interface_config> + <motetype_identifier>node</motetype_identifier> + </mote> + </simulation> + <plugin> + org.contikios.cooja.plugins.SimControl + <width>259</width> + <z>4</z> + <height>179</height> + <location_x>0</location_x> + <location_y>0</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.Visualizer + <plugin_config> + <skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin> + <skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin> + <skin>org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin</skin> + <viewport>2.898638306051894 0.0 0.0 2.898638306051894 -68.40918308040007 -27.82360366026197</viewport> + </plugin_config> + <width>258</width> + <z>2</z> + <height>209</height> + <location_x>0</location_x> + <location_y>178</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.LogListener + <width>1024</width> + <z>3</z> + <height>311</height> + <location_x>0</location_x> + <location_y>385</location_y> + </plugin> +</simconf> diff --git a/arch/platform/native/dev/vib-sensor.c b/examples/libs/stack-check/example-stack-check.c similarity index 63% rename from arch/platform/native/dev/vib-sensor.c rename to examples/libs/stack-check/example-stack-check.c index d5494142deeaff8297fb858b307674dabe3e5b04..8f4b0f0aee9dc60db2380de5d778f8c6d1b0bccf 100644 --- a/arch/platform/native/dev/vib-sensor.c +++ b/examples/libs/stack-check/example-stack-check.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Swedish Institute of Computer Science. + * Copyright (c) 2017, University of Bristol - http://www.bris.ac.uk/ * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,48 +26,63 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * This file is part of the Configurable Sensor Network Application - * Architecture for sensor nodes running the Contiki operating system. - * - * - * ----------------------------------------------------------------- - * - * Author : Adam Dunkels, Joakim Eriksson, Niclas Finne - * Created : 2005-11-01 - * Updated : $Date: 2010/01/14 15:38:56 $ - * $Revision: 1.2 $ */ -#include "dev/vib-sensor.h" +/** + * \file + * Test of Contiki system's stack checker functionality + * \author + * Atis Elsts <atis.elsts@bristol.ac.uk> + */ -const struct sensors_sensor vib_sensor; -static unsigned int vib; +#include "contiki.h" +#include "sys/stack-check.h" +#include "random.h" +#include <stdio.h> +#include <string.h> +#include <alloca.h> /*---------------------------------------------------------------------------*/ -void -vib_sensor_changed(void) -{ - vib++; - sensors_changed(&vib_sensor); -} +PROCESS(example_process, "Stack check example"); +AUTOSTART_PROCESSES(&example_process); /*---------------------------------------------------------------------------*/ -static int -value(int type) +static void +nested_function(void) { - return vib; + printf("stack usage: %u permitted: %u\n", + stack_check_get_usage(), stack_check_get_reserved_size()); } /*---------------------------------------------------------------------------*/ -static int -configure(int type, int c) +static void +test_function(void) { - return 0; + void *p; + uint16_t s; + + /* allocate and fill some random bytes */ + s = random_rand() % 1000; + printf("allocating %u bytes on the stack\n", s); + p = alloca(s); + memset(p, 0, s); + + /* call the nested function to print stack usage */ + nested_function(); } /*---------------------------------------------------------------------------*/ -static int -status(int type) +PROCESS_THREAD(example_process, ev, data) { - return 0; + static struct etimer et; + + PROCESS_BEGIN(); + + while(1) { + etimer_set(&et, CLOCK_SECOND * 2); + + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + test_function(); + } + + PROCESS_END(); } /*---------------------------------------------------------------------------*/ -SENSORS_SENSOR(vib_sensor, VIB_SENSOR, - value, configure, status); diff --git a/examples/platform-specific/jn516x/tsch/tools/rpl-tools.h b/examples/libs/stack-check/project-conf.h similarity index 84% rename from examples/platform-specific/jn516x/tsch/tools/rpl-tools.h rename to examples/libs/stack-check/project-conf.h index b04cdb71217e81f894ca0284435e9c65075f48b3..a9cbe226501d49fba430cd1fc65451b6a4ecc551 100644 --- a/examples/platform-specific/jn516x/tsch/tools/rpl-tools.h +++ b/examples/libs/stack-check/project-conf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Swedish Institute of Computer Science. + * Copyright (c) 2017, University of Bristol - http://www.bris.ac.uk/ * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,10 +27,18 @@ * SUCH DAMAGE. * */ -/** - * \author Simon Duquennoy <simonduq@sics.se> +/** + * \file + * Project config file + * \author + * Atis Elsts <atis.elsts@bristol.ac.uk> + * */ -void rpl_tools_init(uip_ipaddr_t *br_prefix); -void print_network_status(void); +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#define STACK_CHECK_CONF_ENABLED 1 + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/libs/trickle-library/trickle-library.c b/examples/libs/trickle-library/trickle-library.c index 30e02caf0c26d0fe1abfcdaa9cd76953c058806f..c449aade9f1eb1be47611bf2e78181a48aae7db0 100644 --- a/examples/libs/trickle-library/trickle-library.c +++ b/examples/libs/trickle-library/trickle-library.c @@ -36,7 +36,6 @@ #include "contiki-net.h" #include "lib/trickle-timer.h" -#include "dev/leds.h" #include "lib/random.h" #include <string.h> @@ -80,7 +79,6 @@ AUTOSTART_PROCESSES(&trickle_protocol_process); static void tcpip_handler(void) { - leds_on(LEDS_GREEN); if(uip_newdata()) { PRINTF("At %lu (I=%lu, c=%u): ", (unsigned long)clock_time(), (unsigned long)tt.i_cur, tt.c); @@ -109,7 +107,6 @@ tcpip_handler(void) tt.ct.etimer.timer.interval)); } } - leds_off(LEDS_GREEN); return; } /*---------------------------------------------------------------------------*/ @@ -126,8 +123,6 @@ trickle_tx(void *ptr, uint8_t suppress) return; } - leds_on(LEDS_RED); - PRINTF("At %lu (I=%lu, c=%u): ", (unsigned long)clock_time(), (unsigned long)loc_tt->i_cur, loc_tt->c); @@ -144,8 +139,6 @@ trickle_tx(void *ptr, uint8_t suppress) /* Restore to 'accept incoming from any IP' */ uip_create_unspecified(&trickle_conn->ripaddr); - - leds_off(LEDS_RED); } /*---------------------------------------------------------------------------*/ PROCESS_THREAD(trickle_protocol_process, ev, data) diff --git a/examples/libs/trickle-library/trickle-library.csc b/examples/libs/trickle-library/trickle-library.csc index bea3f6c3e1369edb37b3f48fccc401cb0a99ac8b..a450f15e8a48f8ae602e36abb8d31d75846649ca 100644 --- a/examples/libs/trickle-library/trickle-library.csc +++ b/examples/libs/trickle-library/trickle-library.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[CONTIKI_DIR]/tools/cooja/apps/mspsim</project> <project EXPORT="discard">[CONTIKI_DIR]/tools/cooja/apps/avrora</project> <project EXPORT="discard">[CONTIKI_DIR]/tools/cooja/apps/serial_socket</project> - <project EXPORT="discard">[CONTIKI_DIR]/tools/cooja/apps/collect-view</project> <project EXPORT="discard">[CONTIKI_DIR]/tools/cooja/apps/powertracker</project> <simulation> <title>Example Demonstrating the Trickle Library's Functionality</title> diff --git a/examples/lwm2m-ipso-objects/Makefile b/examples/lwm2m-ipso-objects/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..7fa79d1ee920265f4c016c78780fa6ee5de8e988 --- /dev/null +++ b/examples/lwm2m-ipso-objects/Makefile @@ -0,0 +1,14 @@ +CONTIKI_PROJECT = example-ipso-objects + +CONTIKI_SOURCEFILES += serial-protocol.c example-ipso-temperature.c + +PLATFORMS_EXCLUDE = sky + +all: $(CONTIKI_PROJECT) + +MODULES += os/net/app-layer/coap +MODULES += os/services/lwm2m +MODULES += os/services/ipso-objects + +CONTIKI=../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/lwm2m-ipso-objects/README.md b/examples/lwm2m-ipso-objects/README.md new file mode 100644 index 0000000000000000000000000000000000000000..d31b3a84430996449351156d063e421858bd3f4a --- /dev/null +++ b/examples/lwm2m-ipso-objects/README.md @@ -0,0 +1,10 @@ +LWM2M with IPSO Objects Example +============================================ + +This is an OMA LWM2M example implementing IPSO Objects. +It can connect to a Leshan server out-of-the-box. +Important configuration parameters: +* `LWM2M_SERVER_ADDRESS`: the address of the server to register to (or bootstrap from) +* `REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER`: set to bootstrap via `LWM2M_SERVER_ADDRESS` and then obtain the registration server address + +A tutorial for setting up this example is provided on the wiki. diff --git a/examples/lwm2m-ipso-objects/example-ipso-objects.c b/examples/lwm2m-ipso-objects/example-ipso-objects.c new file mode 100644 index 0000000000000000000000000000000000000000..013c62205705dd593ebdcaad3955cd328e26a001 --- /dev/null +++ b/examples/lwm2m-ipso-objects/example-ipso-objects.c @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2015, Yanzi Networks AB. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \file + * OMA LWM2M and IPSO Objects example. + * \author + * Joakim Eriksson, joakime@sics.se + * Niclas Finne, nfi@sics.se + */ + +#include "contiki.h" +#include "dev/leds.h" +#include "services/lwm2m/lwm2m-engine.h" +#include "services/lwm2m/lwm2m-rd-client.h" +#include "services/lwm2m/lwm2m-device.h" +#include "services/lwm2m/lwm2m-server.h" +#include "services/lwm2m/lwm2m-security.h" +#include "services/ipso-objects/ipso-objects.h" +#include "services/ipso-objects/ipso-sensor-template.h" +#include "services/ipso-objects/ipso-control-template.h" +#include "dev/leds.h" + +#define DEBUG DEBUG_NONE +#include "net/ipv6/uip-debug.h" + +#ifndef REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER +#define REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER 0 +#endif + +#ifndef REGISTER_WITH_LWM2M_SERVER +#define REGISTER_WITH_LWM2M_SERVER 1 +#endif + +#ifndef LWM2M_SERVER_ADDRESS +#define LWM2M_SERVER_ADDRESS "coap://[fd00::1]" +#endif + +#if BOARD_SENSORTAG +#include "board-peripherals.h" + +/* Temperature reading */ +static lwm2m_status_t +read_temp_value(const ipso_sensor_t *s, int32_t *value) +{ + *value = 10 * hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_TEMP); + return LWM2M_STATUS_OK; +} +/* Humitidy reading */ +static lwm2m_status_t +read_hum_value(const ipso_sensor_t *s, int32_t *value) +{ + *value = 10 * hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_HUMIDITY); + return LWM2M_STATUS_OK; +} +/* Lux reading */ +static lwm2m_status_t +read_lux_value(const ipso_sensor_t *s, int32_t *value) +{ + *value = 10 * opt_3001_sensor.value(0); + return LWM2M_STATUS_OK; +} +/* Barometer reading */ +static lwm2m_status_t +read_bar_value(const ipso_sensor_t *s, int32_t *value) +{ + *value = 10 * bmp_280_sensor.value(BMP_280_SENSOR_TYPE_PRESS); + return LWM2M_STATUS_OK; +} +/* LED control */ +static lwm2m_status_t +leds_set_val(ipso_control_t *control, uint8_t value) +{ + if(value > 0) { + leds_single_on(LEDS_LED1); + } else { + leds_single_off(LEDS_LED1); + } + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ + +IPSO_CONTROL(led_control, 3311, 0, leds_set_val); + +IPSO_SENSOR(temp_sensor, 3303, read_temp_value, + .max_range = 100000, /* 100 cel milli celcius */ + .min_range = -10000, /* -10 cel milli celcius */ + .unit = "Cel", + .update_interval = 30 + ); + +IPSO_SENSOR(hum_sensor, 3304, read_hum_value, + .max_range = 100000, /* 100 % RH */ + .min_range = 0, + .unit = "% RH", + .update_interval = 30 + ); + +IPSO_SENSOR(lux_sensor, 3301, read_lux_value, + .max_range = 100000, + .min_range = -10000, + .unit = "LUX", + .update_interval = 30 + ); + +IPSO_SENSOR(bar_sensor, 3315, read_bar_value, + .max_range = 100000, /* 100 cel milli celcius */ + .min_range = -10000, /* -10 cel milli celcius */ + .unit = "hPa", + .update_interval = 30 + ); +#endif /* BOARD_SENSORTAG */ + +PROCESS(example_ipso_objects, "IPSO object example"); +AUTOSTART_PROCESSES(&example_ipso_objects); +/*---------------------------------------------------------------------------*/ +static void +setup_lwm2m_servers(void) +{ +#ifdef LWM2M_SERVER_ADDRESS + coap_endpoint_t server_ep; + if(coap_endpoint_parse(LWM2M_SERVER_ADDRESS, strlen(LWM2M_SERVER_ADDRESS), + &server_ep) != 0) { + lwm2m_rd_client_register_with_bootstrap_server(&server_ep); + lwm2m_rd_client_register_with_server(&server_ep); + } +#endif /* LWM2M_SERVER_ADDRESS */ + + lwm2m_rd_client_use_bootstrap_server(REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER); + lwm2m_rd_client_use_registration_server(REGISTER_WITH_LWM2M_SERVER); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(example_ipso_objects, ev, data) +{ + static struct etimer periodic; + PROCESS_BEGIN(); + + PROCESS_PAUSE(); + + PRINTF("Starting IPSO objects example%s\n", + REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER ? " (bootstrap)" : ""); + /* Initialize the OMA LWM2M engine */ + lwm2m_engine_init(); + + /* Register default LWM2M objects */ + lwm2m_device_init(); + lwm2m_security_init(); + lwm2m_server_init(); + +#if BOARD_SENSORTAG + ipso_sensor_add(&temp_sensor); + ipso_sensor_add(&hum_sensor); + ipso_sensor_add(&lux_sensor); + ipso_sensor_add(&bar_sensor); + ipso_control_add(&led_control); + ipso_button_init(); + + SENSORS_ACTIVATE(hdc_1000_sensor); + SENSORS_ACTIVATE(opt_3001_sensor); + SENSORS_ACTIVATE(bmp_280_sensor); +#else /* BOARD_SENSORTAG */ + /* Register default IPSO objects - such as button..*/ + ipso_objects_init(); +#endif /* BOARD_SENSORTAG */ + + setup_lwm2m_servers(); + /* Tick loop each 5 seconds */ + etimer_set(&periodic, CLOCK_SECOND * 5); + + while(1) { + PROCESS_WAIT_EVENT(); + if(ev == PROCESS_EVENT_TIMER && etimer_expired(&periodic)) { +#if BOARD_SENSORTAG + /* deactive / activate to do a new reading */ + SENSORS_DEACTIVATE(hdc_1000_sensor); + SENSORS_DEACTIVATE(opt_3001_sensor); + SENSORS_DEACTIVATE(bmp_280_sensor); + + SENSORS_ACTIVATE(hdc_1000_sensor); + SENSORS_ACTIVATE(opt_3001_sensor); + SENSORS_ACTIVATE(bmp_280_sensor); +#endif /* BOARD_SENSORTAG */ + etimer_reset(&periodic); + } + } + PROCESS_END(); +} diff --git a/examples/ipso-objects/example-ipso-temperature.c b/examples/lwm2m-ipso-objects/example-ipso-temperature.c similarity index 100% rename from examples/ipso-objects/example-ipso-temperature.c rename to examples/lwm2m-ipso-objects/example-ipso-temperature.c diff --git a/examples/ipso-objects/example-server.c b/examples/lwm2m-ipso-objects/example-server.c similarity index 67% rename from examples/ipso-objects/example-server.c rename to examples/lwm2m-ipso-objects/example-server.c index acec7ee252951cebf13f7c300862ba25323e5373..0b55b80a2d6d8804ecee22e73568150e611ea730 100644 --- a/examples/ipso-objects/example-server.c +++ b/examples/lwm2m-ipso-objects/example-server.c @@ -38,20 +38,23 @@ #include "contiki.h" #include "net/ipv6/uip.h" -#include "rpl.h" -#include "rpl-dag-root.h" +#include "net/ipv6/uip-ds6.h" #include "net/netstack.h" -#include "coap-constants.h" -#include "coap-engine.h" +#include "net/routing/routing.h" +#include "coap-transport.h" +#include "coap-blocking-api.h" #include "lwm2m-engine.h" -#include "oma-tlv.h" +#include "lwm2m-tlv.h" #include "dev/serial-line.h" #include "serial-protocol.h" +#include <stdbool.h> #define DEBUG DEBUG_PRINT #include "net/ipv6/uip-debug.h" -#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) +#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) + +#define EVENT_RUN_NOW 0 #define URL_WELL_KNOWN ".well-known/core" #define URL_DEVICE_MODEL "/3/0/1" @@ -64,8 +67,8 @@ #define NODE_HAS_TYPE (1 << 0) struct node { - uip_ipaddr_t ipaddr; - char type[32]; + coap_endpoint_t endpoint; + char type[64]; uint8_t flags; uint8_t retries; }; @@ -87,13 +90,15 @@ add_node(const uip_ipaddr_t *addr) { int i; for(i = 0; i < node_count; i++) { - if(uip_ipaddr_cmp(&nodes[i].ipaddr, addr)) { + if(uip_ipaddr_cmp(&nodes[i].endpoint.ipaddr, addr)) { /* Node already added */ return &nodes[i]; } } if(node_count < MAX_NODES) { - uip_ipaddr_copy(&nodes[node_count].ipaddr, addr); + memset(&nodes[node_count].endpoint, 0, sizeof(coap_endpoint_t)); + uip_ipaddr_copy(&nodes[node_count].endpoint.ipaddr, addr); + nodes[node_count].endpoint.port = REMOTE_PORT; return &nodes[node_count++]; } return NULL; @@ -108,13 +113,13 @@ set_value(const uip_ipaddr_t *addr, char *uri, char *value) printf(" URI: %s Value: %s\n", uri, value); for(i = 0; i < node_count; i++) { - if(uip_ipaddr_cmp(&nodes[i].ipaddr, addr)) { + if(uip_ipaddr_cmp(&nodes[i].endpoint.ipaddr, addr)) { /* setup command */ current_target = &nodes[i]; current_request = COAP_PUT; strncpy(current_uri, uri, sizeof(current_uri) - 1); strncpy(current_value, value, sizeof(current_value) - 1); - process_poll(&router_process); + process_post(&router_process, EVENT_RUN_NOW, NULL); break; } } @@ -129,13 +134,13 @@ get_value(const uip_ipaddr_t *addr, char *uri) printf(" URI: %s\n", uri); for(i = 0; i < node_count; i++) { - if(uip_ipaddr_cmp(&nodes[i].ipaddr, addr)) { + if(uip_ipaddr_cmp(&nodes[i].endpoint.ipaddr, addr)) { /* setup command */ current_target = &nodes[i]; current_request = COAP_GET; strncpy(current_uri, uri, sizeof(current_uri) - 1); current_value[0] = 0; - process_poll(&router_process); + process_post(&router_process, EVENT_RUN_NOW, NULL); break; } } @@ -152,7 +157,7 @@ print_node_list(void) printf(";"); } printf("%s,", nodes[i].type); - uip_debug_ipaddr_print(&nodes[i].ipaddr); + uip_debug_ipaddr_print(&nodes[i].endpoint.ipaddr); } } printf("\n"); @@ -163,7 +168,7 @@ print_node_list(void) * handle responses. */ static void -client_chunk_handler(void *response) +client_chunk_handler(coap_message_t *response) { const uint8_t *chunk; unsigned int format; @@ -173,7 +178,9 @@ client_chunk_handler(void *response) /* if(len > 0) { */ /* printf("|%.*s (%d,%d)", len, (char *)chunk, len, format); */ /* } */ - if(current_target != NULL && fetching_type) { + if(response->code >= BAD_REQUEST_4_00) { + PRINTF("\nReceived error %u: %.*s\n", response->code, len, (char *)chunk); + } else if(current_target != NULL && fetching_type) { if(len > sizeof(current_target->type) - 1) { len = sizeof(current_target->type) - 1; } @@ -182,19 +189,21 @@ client_chunk_handler(void *response) current_target->flags |= NODE_HAS_TYPE; PRINTF("\nNODE "); - PRINT6ADDR(¤t_target->ipaddr); + PRINT6ADDR(¤t_target->endpoint.ipaddr); PRINTF(" HAS TYPE %s\n", current_target->type); } else { /* otherwise update the current value */ if(format == LWM2M_TLV) { - oma_tlv_t tlv; + lwm2m_tlv_t tlv; /* we can only read int32 for now ? */ - if(oma_tlv_read(&tlv, chunk, len) > 0) { + if(lwm2m_tlv_read(&tlv, chunk, len) > 0) { /* printf("TLV.type=%d len=%d id=%d value[0]=%d\n", */ /* tlv.type, tlv.length, tlv.id, tlv.value[0]); */ - int value = oma_tlv_get_int32(&tlv); - snprintf(current_value, sizeof(current_value), "%d", value); + int value = lwm2m_tlv_get_int32(&tlv); + snprintf(current_value, sizeof(current_value) - 1, "%d", value); + } else { + PRINTF("Failed to parse LWM2M TLV\n"); } } else { if(len > sizeof(current_value) - 1) { @@ -206,72 +215,84 @@ client_chunk_handler(void *response) } } /*---------------------------------------------------------------------------*/ -static void -setup_network(void) +#if UIP_CONF_IPV6_RPL +static bool +check_rpl_routes(void) { - uip_ipaddr_t ipaddr; - struct uip_ds6_addr *root_if; - rpl_dag_t *dag; - int i; - uint8_t state; + uip_sr_node_t *link; + uip_ipaddr_t child_ipaddr; + uip_ipaddr_t parent_ipaddr; -#if UIP_CONF_ROUTER -/** - * The choice of server address determines its 6LoWPAN header compression. - * Obviously the choice made here must also be selected in udp-client.c. - * - * For correct Wireshark decoding using a sniffer, add the /64 prefix to the 6LowPAN protocol preferences, - * e.g. set Context 0 to fd00::. At present Wireshark copies Context/128 and then overwrites it. - * (Setting Context 0 to fd00::1111:2222:3333:4444 will report a 16 bit compressed address of fd00::1111:22ff:fe33:xxxx) - * Note Wireshark's IPCMV6 checksum verification depends on the correct uncompressed addresses. - */ -#if 0 -/* Mode 1 - 64 bits inline */ - uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 1); -#elif 1 -/* Mode 2 - 16 bits inline */ - uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0x00ff, 0xfe00, 1); -#else -/* Mode 3 - derived from link local (MAC) address */ - uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); - uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); -#endif - - rpl_dag_root_init(&ipaddr, &ipaddr); - rpl_dag_root_init_dag_immediately(); -#endif /* UIP_CONF_ROUTER */ - - PRINTF("IPv6 addresses: "); - for(i = 0; i < UIP_DS6_ADDR_NB; i++) { - state = uip_ds6_if.addr_list[i].state; - if(state == ADDR_TENTATIVE || state == ADDR_PREFERRED) { - PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); - PRINTF("\n"); - /* hack to make address "final" */ - if (state == ADDR_TENTATIVE) { - uip_ds6_if.addr_list[i].state = ADDR_PREFERRED; - } + /* Our routing links */ + for(link = uip_sr_node_head(); link != NULL; link = uip_sr_node_next(link)) { + NETSTACK_ROUTING.get_sr_node_ipaddr(&child_ipaddr, link); + + if(link->parent == NULL) { + /* Igore the DAG root */ + continue; + } + + current_target = add_node(&child_ipaddr); + if(current_target == NULL || + (current_target->flags & NODE_HAS_TYPE) != 0 || + current_target->retries > 5) { + continue; } + + NETSTACK_ROUTING.get_sr_node_ipaddr(&parent_ipaddr, link->parent); + PRINTF(" "); + PRINT6ADDR(&child_ipaddr); + PRINTF(" -> "); + PRINT6ADDR(&parent_ipaddr); + PRINTF("\n"); + return true; } + return false; } +#endif /* UIP_CONF_IPV6_RPL */ +/*---------------------------------------------------------------------------*/ +#if (UIP_MAX_ROUTES != 0) +static bool +check_routes(void) +{ + uip_ds6_route_t *r; + + for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { + current_target = add_node(&r->ipaddr); + if(current_target == NULL || + (current_target->flags & NODE_HAS_TYPE) != 0 || + current_target->retries > 5) { + continue; + } + PRINTF(" "); + PRINT6ADDR(&r->ipaddr); + PRINTF(" -> "); + nexthop = uip_ds6_route_nexthop(r); + if(nexthop != NULL) { + PRINT6ADDR(nexthop); + } else { + PRINTF("-"); + } + PRINTF("\n"); + return true; + } + return false; +} +#endif /* (UIP_MAX_ROUTES != 0) */ /*---------------------------------------------------------------------------*/ PROCESS_THREAD(router_process, ev, data) { - /* This way the packet can be treated as pointer as usual. */ - static coap_packet_t request[1]; + /* This way the message can be treated as pointer as usual. */ + static coap_message_t request[1]; static struct etimer timer; - uip_ds6_route_t *r; - uip_ipaddr_t *nexthop; - int n; PROCESS_BEGIN(); - PROCESS_PAUSE(); - /* receives all CoAP messages */ - coap_init_engine(); + coap_engine_init(); - setup_network(); + /* Initialize DAG root */ + NETSTACK_ROUTING.root_start(); while(1) { etimer_set(&timer, CLOCK_SECOND * 5); @@ -284,28 +305,15 @@ PROCESS_THREAD(router_process, ev, data) if(etimer_expired(&timer)) { current_target = NULL; - n = 0; - for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { - current_target = add_node(&r->ipaddr); - if(current_target == NULL || - (current_target->flags & NODE_HAS_TYPE) != 0 || - current_target->retries > 5) { - continue; - } - PRINTF(" "); - PRINT6ADDR(&r->ipaddr); - PRINTF(" -> "); - nexthop = uip_ds6_route_nexthop(r); - if(nexthop != NULL) { - PRINT6ADDR(nexthop); - PRINTF("\n"); - } else { - PRINTF("-"); - } - PRINTF("\n"); - n++; - break; +#if UIP_CONF_IPV6_RPL + check_rpl_routes(); +#endif /* UIP_CONF_IPV6_RPL */ + +#if (UIP_MAX_ROUTES != 0) + if(current_target == NULL) { + check_routes(); } +#endif /* (UIP_MAX_ROUTES != 0) */ } /* This is a node type discovery */ @@ -320,15 +328,15 @@ PROCESS_THREAD(router_process, ev, data) current_target->retries++; PRINTF("CoAP request to ["); - PRINT6ADDR(¤t_target->ipaddr); - PRINTF("]:%u (%u tx)\n", UIP_HTONS(REMOTE_PORT), + PRINT6ADDR(¤t_target->endpoint.ipaddr); + PRINTF("]:%u (%u tx)\n", UIP_HTONS(current_target->endpoint.port), current_target->retries); fetching_type = 1; - COAP_BLOCKING_REQUEST(¤t_target->ipaddr, REMOTE_PORT, request, + COAP_BLOCKING_REQUEST(¤t_target->endpoint, request, client_chunk_handler); fetching_type = 0; - strncpy(current_uri, URL_LIGHT_CONTROL, sizeof(current_uri)); + strncpy(current_uri, URL_LIGHT_CONTROL, sizeof(current_uri) - 1); printf("\n--Done--\n"); } @@ -345,10 +353,11 @@ PROCESS_THREAD(router_process, ev, data) } PRINTF("CoAP request to ["); - PRINT6ADDR(¤t_target->ipaddr); - PRINTF("]:%u %s\n", UIP_HTONS(REMOTE_PORT), current_uri); + PRINT6ADDR(¤t_target->endpoint.ipaddr); + PRINTF("]:%u %s\n", UIP_HTONS(current_target->endpoint.port), + current_uri); - COAP_BLOCKING_REQUEST(¤t_target->ipaddr, REMOTE_PORT, request, + COAP_BLOCKING_REQUEST(¤t_target->endpoint, request, client_chunk_handler); /* print out result of command */ @@ -357,13 +366,12 @@ PROCESS_THREAD(router_process, ev, data) } else { printf("g "); } - uip_debug_ipaddr_print(¤t_target->ipaddr); + uip_debug_ipaddr_print(¤t_target->endpoint.ipaddr); printf(" %s %s\n", current_uri, current_value); current_target = NULL; current_uri[0] = 0; current_value[0] = 0; - } } diff --git a/examples/ipso-objects/project-conf.h b/examples/lwm2m-ipso-objects/project-conf.h similarity index 92% rename from examples/ipso-objects/project-conf.h rename to examples/lwm2m-ipso-objects/project-conf.h index 075cd7444ed2bc41c6077239a7e2c2d8211b1bf1..a7ad8b3ea2a158ad5b3c7f3f6a17bef45e65a7d7 100644 --- a/examples/ipso-objects/project-conf.h +++ b/examples/lwm2m-ipso-objects/project-conf.h @@ -30,6 +30,9 @@ #ifndef PROJECT_CONF_H_ #define PROJECT_CONF_H_ +/* No sleep on CC2538 to enable full 32 KiB RAM */ +#define LPM_CONF_ENABLE 0 + #ifdef BOARD_STRING #define LWM2M_DEVICE_MODEL_NUMBER BOARD_STRING #elif defined(CONTIKI_TARGET_WISMOTE) @@ -40,10 +43,14 @@ #define PLATFORM_REBOOT watchdog_reboot #endif +#if BOARD_SENSORTAG +/* Real sensor is present... */ +#else #define IPSO_TEMPERATURE example_ipso_temperature +#endif /* BOARD_SENSORTAG */ /* Increase rpl-border-router IP-buffer when using more than 64. */ -#define REST_MAX_CHUNK_SIZE 64 +#define COAP_MAX_CHUNK_SIZE 64 /* Multiplies with chunk size, be aware of memory constraints. */ #define COAP_MAX_OPEN_TRANSACTIONS 4 diff --git a/examples/ipso-objects/serial-protocol.c b/examples/lwm2m-ipso-objects/serial-protocol.c similarity index 97% rename from examples/ipso-objects/serial-protocol.c rename to examples/lwm2m-ipso-objects/serial-protocol.c index bc59294f6603135ccdb474e8e3d9db606b682d5d..00c7e0139a9ff7b51ff14a9f41fdd6c3fa1de5e7 100644 --- a/examples/ipso-objects/serial-protocol.c +++ b/examples/lwm2m-ipso-objects/serial-protocol.c @@ -60,7 +60,7 @@ find_next_sep(const char *str, char sep, int pos) /* * l - list all discovered devices * s - set <IP> <URI> <value> - * d - get <IP> <URI> + * g - get <IP> <URI> */ void serial_protocol_input(char *data) @@ -119,8 +119,12 @@ serial_protocol_input(char *data) } break; } + case '\0': + /* Ignore empty lines */ + break; default: printf("Unknown command\n"); } + printf("> "); } /*---------------------------------------------------------------------------*/ diff --git a/examples/ipso-objects/serial-protocol.h b/examples/lwm2m-ipso-objects/serial-protocol.h similarity index 100% rename from examples/ipso-objects/serial-protocol.h rename to examples/lwm2m-ipso-objects/serial-protocol.h diff --git a/examples/mqtt-client/Makefile b/examples/mqtt-client/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d315cfea34ee0c3622659beef2449e9472568fb7 --- /dev/null +++ b/examples/mqtt-client/Makefile @@ -0,0 +1,13 @@ +CONTIKI_PROJECT = mqtt-client +all: $(CONTIKI_PROJECT) + +MODULES += os/net/app-layer/mqtt + +CONTIKI = ../.. +-include $(CONTIKI)/Makefile.identify-target + +MODULES_REL += arch/platform/$(TARGET) + +PLATFORMS_ONLY = srf06-cc26xx cc2538dk openmote-cc2538 zoul native + +include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/cc2538-common/mqtt-demo/README.md b/examples/mqtt-client/README.md similarity index 90% rename from examples/platform-specific/cc2538-common/mqtt-demo/README.md rename to examples/mqtt-client/README.md index 8b4e3b043cef6622019e97606e487c0281fa2383..44bba8877e798ff89d2d45902215d856a512f1f6 100644 --- a/examples/platform-specific/cc2538-common/mqtt-demo/README.md +++ b/examples/mqtt-client/README.md @@ -1,15 +1,18 @@ -MQTT Demo -========= +MQTT Client Example +=================== The MQTT client can be used to: * Publish sensor readings to an MQTT broker. * Subscribe to a topic and receive commands from an MQTT broker -The demo will give some visual feedback with the green LED: +The demo will give some visual feedback with a LED (configurable): * Very fast blinking: Searching for a network * Fast blinking: Connecting to broker * Slow, long blinking: Sending a publish message +This example is known to work with all platforms that support the new button +API. + Publishing ---------- By default the example will attempt to publish readings to an MQTT broker @@ -20,7 +23,7 @@ running on the IPv6 address specified as `MQTT_DEMO_BROKER_IP_ADDR` in The publish messages include sensor readings but also some other information, such as device uptime in seconds and a message sequence number. The demo will publish to topic `iot-2/evt/status/fmt/json`. The device will connect using -client-id `d:quickstart:cc2538:<device-id>`, where `<device-id>` gets +client-id `d:contiki-ng:mqtt-client:<device-id>`, where `<device-id>` gets constructed from the device's IEEE address. Subscribing diff --git a/examples/mqtt-client/arch/cpu/cc2538/builtin-sensors.c b/examples/mqtt-client/arch/cpu/cc2538/builtin-sensors.c new file mode 100644 index 0000000000000000000000000000000000000000..f22c33835882655b6499aa35eee7a00885c97b8b --- /dev/null +++ b/examples/mqtt-client/arch/cpu/cc2538/builtin-sensors.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/cc2538-sensors.h" +#include "mqtt-client.h" + +#include <string.h> +#include <stdio.h> +/*---------------------------------------------------------------------------*/ +#define TMP_BUF_SZ 32 +/*---------------------------------------------------------------------------*/ +char tmp_buf[TMP_BUF_SZ]; +/*---------------------------------------------------------------------------*/ +static char * +temp_reading(void) +{ + memset(tmp_buf, 0, TMP_BUF_SZ); + snprintf(tmp_buf, TMP_BUF_SZ, "\"On-Chip Temp (mC)\":%d", + cc2538_temp_sensor.value(CC2538_SENSORS_VALUE_TYPE_CONVERTED)); + return tmp_buf; +} +/*---------------------------------------------------------------------------*/ +static void +temp_init(void) +{ + SENSORS_ACTIVATE(cc2538_temp_sensor); +} +/*---------------------------------------------------------------------------*/ +const mqtt_client_extension_t builtin_sensors_cc2538_temp = { + temp_init, + temp_reading, +}; +/*---------------------------------------------------------------------------*/ +static char * +vdd3_reading(void) +{ + memset(tmp_buf, 0, TMP_BUF_SZ); + snprintf(tmp_buf, TMP_BUF_SZ, "\"VDD3 (mV)\":%d", + vdd3_sensor.value(CC2538_SENSORS_VALUE_TYPE_CONVERTED)); + return tmp_buf; +} +/*---------------------------------------------------------------------------*/ +static void +vdd3_init(void) +{ + SENSORS_ACTIVATE(vdd3_sensor); +} +/*---------------------------------------------------------------------------*/ +const mqtt_client_extension_t builtin_sensors_vdd3 = { + vdd3_init, + vdd3_reading, +}; +/*---------------------------------------------------------------------------*/ diff --git a/examples/mqtt-client/arch/cpu/cc2538/builtin-sensors.h b/examples/mqtt-client/arch/cpu/cc2538/builtin-sensors.h new file mode 100644 index 0000000000000000000000000000000000000000..50a765b5276f8db5444cc0af4a894b05b9995fe2 --- /dev/null +++ b/examples/mqtt-client/arch/cpu/cc2538/builtin-sensors.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#ifndef BUILTIN_SENSORS_H_ +#define BUILTIN_SENSORS_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "mqtt-client.h" +/*---------------------------------------------------------------------------*/ +extern const mqtt_client_extension_t builtin_sensors_vdd3; +extern const mqtt_client_extension_t builtin_sensors_cc2538_temp; +/*---------------------------------------------------------------------------*/ +#endif /* BUILTIN_SENSORS_H_ */ +/*---------------------------------------------------------------------------*/ diff --git a/examples/mqtt-client/arch/cpu/cc26xx-cc13xx/builtin-sensors.c b/examples/mqtt-client/arch/cpu/cc26xx-cc13xx/builtin-sensors.c new file mode 100644 index 0000000000000000000000000000000000000000..3b346fc1bb260b0d6f95163a4ddd69ea578e1a1a --- /dev/null +++ b/examples/mqtt-client/arch/cpu/cc26xx-cc13xx/builtin-sensors.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "batmon-sensor.h" +#include "mqtt-client.h" + +#include <string.h> +#include <stdio.h> +/*---------------------------------------------------------------------------*/ +#define TMP_BUF_SZ 32 +/*---------------------------------------------------------------------------*/ +char tmp_buf[TMP_BUF_SZ]; +/*---------------------------------------------------------------------------*/ +static char * +temp_reading(void) +{ + memset(tmp_buf, 0, TMP_BUF_SZ); + snprintf(tmp_buf, TMP_BUF_SZ, "\"On-Chip Temp (mC)\":%d", + batmon_sensor.value(BATMON_SENSOR_TYPE_TEMP)); + return tmp_buf; +} +/*---------------------------------------------------------------------------*/ +static void +temp_init(void) +{ + SENSORS_ACTIVATE(batmon_sensor); +} +/*---------------------------------------------------------------------------*/ +const mqtt_client_extension_t builtin_sensors_batmon_temp = { + temp_init, + temp_reading, +}; +/*---------------------------------------------------------------------------*/ +static char * +volt_reading(void) +{ + memset(tmp_buf, 0, TMP_BUF_SZ); + snprintf(tmp_buf, TMP_BUF_SZ, "\"Volt (mV)\":%d", + (batmon_sensor.value(BATMON_SENSOR_TYPE_VOLT) * 125) >> 5); + return tmp_buf; +} +/*---------------------------------------------------------------------------*/ +static void +volt_init(void) +{ + SENSORS_ACTIVATE(batmon_sensor); +} +/*---------------------------------------------------------------------------*/ +const mqtt_client_extension_t builtin_sensors_batmon_volt = { + volt_init, + volt_reading, +}; +/*---------------------------------------------------------------------------*/ diff --git a/examples/mqtt-client/arch/cpu/cc26xx-cc13xx/builtin-sensors.h b/examples/mqtt-client/arch/cpu/cc26xx-cc13xx/builtin-sensors.h new file mode 100644 index 0000000000000000000000000000000000000000..38af3f62af4fb78be872811fbe05a3efd626f303 --- /dev/null +++ b/examples/mqtt-client/arch/cpu/cc26xx-cc13xx/builtin-sensors.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#ifndef BUILTIN_SENSORS_H_ +#define BUILTIN_SENSORS_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "mqtt-client.h" +/*---------------------------------------------------------------------------*/ +extern const mqtt_client_extension_t builtin_sensors_batmon_temp; +extern const mqtt_client_extension_t builtin_sensors_batmon_volt; +/*---------------------------------------------------------------------------*/ +#endif /* BUILTIN_SENSORS_H_ */ +/*---------------------------------------------------------------------------*/ diff --git a/examples/mqtt-client/arch/platform/cc2538dk/Makefile.cc2538dk b/examples/mqtt-client/arch/platform/cc2538dk/Makefile.cc2538dk new file mode 100644 index 0000000000000000000000000000000000000000..fcdd0583a04a0b0ee6ef7a2b99abf447ec88d38d --- /dev/null +++ b/examples/mqtt-client/arch/platform/cc2538dk/Makefile.cc2538dk @@ -0,0 +1 @@ +MODULES_REL += arch/cpu/cc2538 diff --git a/examples/mqtt-client/arch/platform/cc2538dk/als-extend.c b/examples/mqtt-client/arch/platform/cc2538dk/als-extend.c new file mode 100644 index 0000000000000000000000000000000000000000..7f9845a42d8b0278b1224f67eeccafdc904850ad --- /dev/null +++ b/examples/mqtt-client/arch/platform/cc2538dk/als-extend.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "als-extend.h" +#include "dev/als-sensor.h" + +#include <string.h> +#include <stdio.h> +/*---------------------------------------------------------------------------*/ +#define TMP_BUF_SZ 32 +/*---------------------------------------------------------------------------*/ +char tmp_buf[TMP_BUF_SZ]; +/*---------------------------------------------------------------------------*/ +static void +als_init(void) +{ + SENSORS_ACTIVATE(als_sensor); +} +/*---------------------------------------------------------------------------*/ +static char * +als_reading(void) +{ + memset(tmp_buf, 0, TMP_BUF_SZ); + snprintf(tmp_buf, TMP_BUF_SZ, "\"ALS (raw)\":%d", als_sensor.value(0)); + return tmp_buf; +} +/*---------------------------------------------------------------------------*/ +const mqtt_client_extension_t als_extend = { + als_init, + als_reading, +}; +/*---------------------------------------------------------------------------*/ diff --git a/examples/mqtt-client/arch/platform/cc2538dk/als-extend.h b/examples/mqtt-client/arch/platform/cc2538dk/als-extend.h new file mode 100644 index 0000000000000000000000000000000000000000..f9b8dc9b05312d422448821434d190abbe00bb7e --- /dev/null +++ b/examples/mqtt-client/arch/platform/cc2538dk/als-extend.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#ifndef ALS_EXTEND_H_ +#define ALS_EXTEND_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "mqtt-client.h" +/*---------------------------------------------------------------------------*/ +extern const mqtt_client_extension_t als_extend; +/*---------------------------------------------------------------------------*/ +#endif /* ALS_EXTEND_H_ */ +/*---------------------------------------------------------------------------*/ diff --git a/examples/mqtt-client/arch/platform/cc2538dk/module-macros.h b/examples/mqtt-client/arch/platform/cc2538dk/module-macros.h new file mode 100644 index 0000000000000000000000000000000000000000..6f0bce121adf0fec1ef3ba0720bb96f79e9d01e3 --- /dev/null +++ b/examples/mqtt-client/arch/platform/cc2538dk/module-macros.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/* Enable MQTT client extensions */ +#define MQTT_CLIENT_CONF_WITH_EXTENSIONS 1 +/*---------------------------------------------------------------------------*/ diff --git a/examples/mqtt-client/arch/platform/cc2538dk/mqtt-client-extensions.c b/examples/mqtt-client/arch/platform/cc2538dk/mqtt-client-extensions.c new file mode 100644 index 0000000000000000000000000000000000000000..835b95fa6a63391914ac12c7f2ec8a490be20275 --- /dev/null +++ b/examples/mqtt-client/arch/platform/cc2538dk/mqtt-client-extensions.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "builtin-sensors.h" +#include "als-extend.h" +#include "mqtt-client.h" + +#include <string.h> +/*---------------------------------------------------------------------------*/ +MQTT_CLIENT_EXTENSIONS(&builtin_sensors_vdd3, &builtin_sensors_cc2538_temp, + &als_extend); +/*---------------------------------------------------------------------------*/ diff --git a/examples/mqtt-client/arch/platform/openmote-cc2538/Makefile.openmote-cc2538 b/examples/mqtt-client/arch/platform/openmote-cc2538/Makefile.openmote-cc2538 new file mode 100644 index 0000000000000000000000000000000000000000..fcdd0583a04a0b0ee6ef7a2b99abf447ec88d38d --- /dev/null +++ b/examples/mqtt-client/arch/platform/openmote-cc2538/Makefile.openmote-cc2538 @@ -0,0 +1 @@ +MODULES_REL += arch/cpu/cc2538 diff --git a/examples/mqtt-client/arch/platform/openmote-cc2538/module-macros.h b/examples/mqtt-client/arch/platform/openmote-cc2538/module-macros.h new file mode 100644 index 0000000000000000000000000000000000000000..097c26dd8391f8ec4752ed520e0493a25d1eb2fc --- /dev/null +++ b/examples/mqtt-client/arch/platform/openmote-cc2538/module-macros.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/* Enable MQTT client extensions */ +#define MQTT_CLIENT_CONF_WITH_EXTENSIONS 1 +/*---------------------------------------------------------------------------*/ diff --git a/examples/mqtt-client/arch/platform/openmote-cc2538/mqtt-client-extensions.c b/examples/mqtt-client/arch/platform/openmote-cc2538/mqtt-client-extensions.c new file mode 100644 index 0000000000000000000000000000000000000000..022c28e84b903dc8141f5ed1164f28145d8ae161 --- /dev/null +++ b/examples/mqtt-client/arch/platform/openmote-cc2538/mqtt-client-extensions.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "builtin-sensors.h" +#include "mqtt-client.h" + +#include <string.h> +/*---------------------------------------------------------------------------*/ +MQTT_CLIENT_EXTENSIONS(&builtin_sensors_vdd3, &builtin_sensors_cc2538_temp); +/*---------------------------------------------------------------------------*/ diff --git a/examples/mqtt-client/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx b/examples/mqtt-client/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx new file mode 100644 index 0000000000000000000000000000000000000000..dcec87bad6f160196a78bf52e3eeb83da4c77e77 --- /dev/null +++ b/examples/mqtt-client/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx @@ -0,0 +1 @@ +MODULES_REL += arch/cpu/cc26xx-cc13xx diff --git a/examples/mqtt-client/arch/platform/srf06-cc26xx/module-macros.h b/examples/mqtt-client/arch/platform/srf06-cc26xx/module-macros.h new file mode 100644 index 0000000000000000000000000000000000000000..6f0bce121adf0fec1ef3ba0720bb96f79e9d01e3 --- /dev/null +++ b/examples/mqtt-client/arch/platform/srf06-cc26xx/module-macros.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/* Enable MQTT client extensions */ +#define MQTT_CLIENT_CONF_WITH_EXTENSIONS 1 +/*---------------------------------------------------------------------------*/ diff --git a/examples/mqtt-client/arch/platform/srf06-cc26xx/mqtt-client-extensions.c b/examples/mqtt-client/arch/platform/srf06-cc26xx/mqtt-client-extensions.c new file mode 100644 index 0000000000000000000000000000000000000000..559a4ee9b8f577bc7cfcaa39f54dc673599af489 --- /dev/null +++ b/examples/mqtt-client/arch/platform/srf06-cc26xx/mqtt-client-extensions.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "builtin-sensors.h" +#include "mqtt-client.h" + +#include <string.h> +/*---------------------------------------------------------------------------*/ +MQTT_CLIENT_EXTENSIONS(&builtin_sensors_batmon_temp, + &builtin_sensors_batmon_volt); +/*---------------------------------------------------------------------------*/ diff --git a/examples/mqtt-client/arch/platform/zoul/Makefile.zoul b/examples/mqtt-client/arch/platform/zoul/Makefile.zoul new file mode 100644 index 0000000000000000000000000000000000000000..fcdd0583a04a0b0ee6ef7a2b99abf447ec88d38d --- /dev/null +++ b/examples/mqtt-client/arch/platform/zoul/Makefile.zoul @@ -0,0 +1 @@ +MODULES_REL += arch/cpu/cc2538 diff --git a/examples/mqtt-client/arch/platform/zoul/module-macros.h b/examples/mqtt-client/arch/platform/zoul/module-macros.h new file mode 100644 index 0000000000000000000000000000000000000000..6f0bce121adf0fec1ef3ba0720bb96f79e9d01e3 --- /dev/null +++ b/examples/mqtt-client/arch/platform/zoul/module-macros.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/* Enable MQTT client extensions */ +#define MQTT_CLIENT_CONF_WITH_EXTENSIONS 1 +/*---------------------------------------------------------------------------*/ diff --git a/examples/mqtt-client/arch/platform/zoul/mqtt-client-extensions.c b/examples/mqtt-client/arch/platform/zoul/mqtt-client-extensions.c new file mode 100644 index 0000000000000000000000000000000000000000..022c28e84b903dc8141f5ed1164f28145d8ae161 --- /dev/null +++ b/examples/mqtt-client/arch/platform/zoul/mqtt-client-extensions.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "builtin-sensors.h" +#include "mqtt-client.h" + +#include <string.h> +/*---------------------------------------------------------------------------*/ +MQTT_CLIENT_EXTENSIONS(&builtin_sensors_vdd3, &builtin_sensors_cc2538_temp); +/*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/cc2538-common/mqtt-demo/mqtt-demo.c b/examples/mqtt-client/mqtt-client.c similarity index 79% rename from examples/platform-specific/cc2538-common/mqtt-demo/mqtt-demo.c rename to examples/mqtt-client/mqtt-client.c index 18b806ac92e66508cff5933e08b04722f8e5ad40..2586604594fd46a71eaf75ccf3f3d652643746ef 100644 --- a/examples/platform-specific/cc2538-common/mqtt-demo/mqtt-demo.c +++ b/examples/mqtt-client/mqtt-client.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,36 +29,25 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** \addtogroup cc2538-examples - * @{ - * - * \defgroup cc2538-mqtt-demo CC2538 MQTT Demo Project - * - * Demonstrates MQTT functionality. Works with IBM Quickstart as well as - * mosquitto. - * @{ - * - * \file - * An MQTT example for the cc2538-based platforms - */ -/*---------------------------------------------------------------------------*/ #include "contiki.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ +#include "net/routing/routing.h" #include "mqtt.h" -#include "rpl.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-icmp6.h" #include "net/ipv6/sicslowpan.h" #include "sys/etimer.h" #include "sys/ctimer.h" #include "lib/sensors.h" -#include "dev/button-sensor.h" +#include "dev/button-hal.h" #include "dev/leds.h" -#include "dev/cc2538-sensors.h" +#include "os/sys/log.h" +#include "mqtt-client.h" #include <string.h> +#include <strings.h> +/*---------------------------------------------------------------------------*/ +#define LOG_MODULE "mqtt-client" +#define LOG_LEVEL LOG_LEVEL_NONE /*---------------------------------------------------------------------------*/ /* * IBM server: messaging.quickstart.internetofthings.ibmcloud.com @@ -67,14 +57,26 @@ * Alternatively, publish to a local MQTT broker (e.g. mosquitto) running on * the node that hosts your border router */ -#ifdef MQTT_DEMO_BROKER_IP_ADDR -static const char *broker_ip = MQTT_DEMO_BROKER_IP_ADDR; -#define DEFAULT_ORG_ID "mqtt-demo" +#ifdef MQTT_CLIENT_CONF_BROKER_IP_ADDR +static const char *broker_ip = MQTT_CLIENT_CONF_BROKER_IP_ADDR; +#define DEFAULT_ORG_ID "contiki-ng" #else static const char *broker_ip = "0064:ff9b:0000:0000:0000:0000:b8ac:7cbd"; #define DEFAULT_ORG_ID "quickstart" #endif /*---------------------------------------------------------------------------*/ +#ifdef MQTT_CLIENT_CONF_STATUS_LED +#define MQTT_CLIENT_STATUS_LED MQTT_CLIENT_CONF_STATUS_LED +#else +#define MQTT_CLIENT_STATUS_LED LEDS_GREEN +#endif +/*---------------------------------------------------------------------------*/ +#ifdef MQTT_CLIENT_CONF_WITH_EXTENSIONS +#define MQTT_CLIENT_WITH_EXTENSIONS MQTT_CLIENT_CONF_WITH_EXTENSIONS +#else +#define MQTT_CLIENT_WITH_EXTENSIONS 0 +#endif +/*---------------------------------------------------------------------------*/ /* * A timeout used when waiting for something to happen (e.g. to connect or to * disconnect) @@ -130,7 +132,7 @@ static uint8_t state; #define NO_NET_LED_DURATION (NET_CONNECT_PERIODIC >> 1) /*---------------------------------------------------------------------------*/ /* Default configuration values */ -#define DEFAULT_TYPE_ID "cc2538" +#define DEFAULT_TYPE_ID "mqtt-client" #define DEFAULT_AUTH_TOKEN "AUTHZ" #define DEFAULT_EVENT_TYPE_ID "status" #define DEFAULT_SUBSCRIBE_CMD_TYPE "+" @@ -139,14 +141,13 @@ static uint8_t state; #define DEFAULT_KEEP_ALIVE_TIMER 60 #define DEFAULT_RSSI_MEAS_INTERVAL (CLOCK_SECOND * 30) /*---------------------------------------------------------------------------*/ -/* Take a sensor reading on button press */ -#define PUBLISH_TRIGGER &button_sensor - +#define MQTT_CLIENT_SENSOR_NONE (void *)0xFFFFFFFF +/*---------------------------------------------------------------------------*/ /* Payload length of ICMPv6 echo requests used to measure RSSI with def rt */ #define ECHO_REQ_PAYLOAD_LEN 20 /*---------------------------------------------------------------------------*/ -PROCESS_NAME(mqtt_demo_process); -AUTOSTART_PROCESSES(&mqtt_demo_process); +PROCESS_NAME(mqtt_client_process); +AUTOSTART_PROCESSES(&mqtt_client_process); /*---------------------------------------------------------------------------*/ /** * \brief Data structure declaration for the MQTT client configuration @@ -166,8 +167,6 @@ typedef struct mqtt_client_config { /* Maximum TCP segment size for outgoing segments of our socket */ #define MAX_TCP_SEGMENT_SIZE 32 /*---------------------------------------------------------------------------*/ -#define STATUS_LED LEDS_GREEN -/*---------------------------------------------------------------------------*/ /* * Buffers for Client ID and Topic. * Make sure they are large enough to hold the entire respective string @@ -204,9 +203,17 @@ static int def_rt_rssi = 0; /*---------------------------------------------------------------------------*/ static mqtt_client_config_t conf; /*---------------------------------------------------------------------------*/ -PROCESS(mqtt_demo_process, "MQTT Demo"); +#if MQTT_CLIENT_WITH_EXTENSIONS +extern const mqtt_client_extension_t *mqtt_client_extensions[]; +extern const uint8_t mqtt_client_extension_count; +#else +static const mqtt_client_extension_t *mqtt_client_extensions[] = { NULL }; +static const uint8_t mqtt_client_extension_count = 0; +#endif +/*---------------------------------------------------------------------------*/ +PROCESS(mqtt_client_process, "MQTT Client"); /*---------------------------------------------------------------------------*/ -int +static int ipaddr_sprintf(char *buf, uint8_t buf_len, const uip_ipaddr_t *addr) { uint16_t a; @@ -243,25 +250,25 @@ echo_reply_handler(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data, static void publish_led_off(void *d) { - leds_off(STATUS_LED); + leds_off(MQTT_CLIENT_STATUS_LED); } /*---------------------------------------------------------------------------*/ static void pub_handler(const char *topic, uint16_t topic_len, const uint8_t *chunk, uint16_t chunk_len) { - DBG("Pub Handler: topic='%s' (len=%u), chunk_len=%u\n", topic, topic_len, - chunk_len); + LOG_DBG("Pub Handler: topic='%s' (len=%u), chunk_len=%u\n", topic, + topic_len, chunk_len); /* If we don't like the length, ignore */ if(topic_len != 23 || chunk_len != 1) { - printf("Incorrect topic or chunk len. Ignored\n"); + LOG_ERR("Incorrect topic or chunk len. Ignored\n"); return; } /* If the format != json, ignore */ if(strncmp(&topic[topic_len - 4], "json", 4) != 0) { - printf("Incorrect format\n"); + LOG_ERR("Incorrect format\n"); } if(strncmp(&topic[10], "leds", 4) == 0) { @@ -279,16 +286,16 @@ mqtt_event(struct mqtt_connection *m, mqtt_event_t event, void *data) { switch(event) { case MQTT_EVENT_CONNECTED: { - DBG("APP - Application has a MQTT connection\n"); + LOG_DBG("Application has a MQTT connection\n"); timer_set(&connection_life, CONNECTION_STABLE_TIME); state = STATE_CONNECTED; break; } case MQTT_EVENT_DISCONNECTED: { - DBG("APP - MQTT Disconnect. Reason %u\n", *((mqtt_event_t *)data)); + LOG_DBG("MQTT Disconnect. Reason %u\n", *((mqtt_event_t *)data)); state = STATE_DISCONNECTED; - process_poll(&mqtt_demo_process); + process_poll(&mqtt_client_process); break; } case MQTT_EVENT_PUBLISH: { @@ -297,29 +304,28 @@ mqtt_event(struct mqtt_connection *m, mqtt_event_t event, void *data) /* Implement first_flag in publish message? */ if(msg_ptr->first_chunk) { msg_ptr->first_chunk = 0; - DBG("APP - Application received a publish on topic '%s'. Payload " - "size is %i bytes. Content:\n\n", - msg_ptr->topic, msg_ptr->payload_length); + LOG_DBG("Application received publish for topic '%s'. Payload " + "size is %i bytes.\n", msg_ptr->topic, msg_ptr->payload_length); } - pub_handler(msg_ptr->topic, strlen(msg_ptr->topic), msg_ptr->payload_chunk, - msg_ptr->payload_length); + pub_handler(msg_ptr->topic, strlen(msg_ptr->topic), + msg_ptr->payload_chunk, msg_ptr->payload_length); break; } case MQTT_EVENT_SUBACK: { - DBG("APP - Application is subscribed to topic successfully\n"); + LOG_DBG("Application is subscribed to topic successfully\n"); break; } case MQTT_EVENT_UNSUBACK: { - DBG("APP - Application is unsubscribed to topic successfully\n"); + LOG_DBG("Application is unsubscribed to topic successfully\n"); break; } case MQTT_EVENT_PUBACK: { - DBG("APP - Publishing complete.\n"); + LOG_DBG("Publishing complete.\n"); break; } default: - DBG("APP - Application got a unhandled MQTT event: %i\n", event); + LOG_DBG("Application got a unhandled MQTT event: %i\n", event); break; } } @@ -332,7 +338,7 @@ construct_pub_topic(void) /* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */ if(len < 0 || len >= BUFFER_SIZE) { - printf("Pub Topic: %d, Buffer %d\n", len, BUFFER_SIZE); + LOG_INFO("Pub Topic: %d, Buffer %d\n", len, BUFFER_SIZE); return 0; } @@ -347,7 +353,7 @@ construct_sub_topic(void) /* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */ if(len < 0 || len >= BUFFER_SIZE) { - printf("Sub Topic: %d, Buffer %d\n", len, BUFFER_SIZE); + LOG_INFO("Sub Topic: %d, Buffer %d\n", len, BUFFER_SIZE); return 0; } @@ -365,7 +371,7 @@ construct_client_id(void) /* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */ if(len < 0 || len >= BUFFER_SIZE) { - printf("Client ID: %d, Buffer %d\n", len, BUFFER_SIZE); + LOG_ERR("Client ID: %d, Buffer %d\n", len, BUFFER_SIZE); return 0; } @@ -440,9 +446,9 @@ subscribe(void) status = mqtt_subscribe(&conn, NULL, sub_topic, MQTT_QOS_LEVEL_0); - DBG("APP - Subscribing!\n"); + LOG_DBG("Subscribing!\n"); if(status == MQTT_STATUS_OUT_QUEUE_FULL) { - DBG("APP - Tried to subscribe but command queue was full!\n"); + LOG_ERR("Tried to subscribe but command queue was full!\n"); } } /*---------------------------------------------------------------------------*/ @@ -452,6 +458,7 @@ publish(void) /* Publish MQTT topic in IBM quickstart format */ int len; int remaining = APP_BUFFER_SIZE; + int i; seq_nr_value++; @@ -460,13 +467,17 @@ publish(void) len = snprintf(buf_ptr, remaining, "{" "\"d\":{" - "\"myName\":\"%s\"," + "\"Platform\":\""CONTIKI_TARGET_STRING"\"," +#ifdef CONTIKI_BOARD_STRING + "\"Board\":\""CONTIKI_BOARD_STRING"\"," +#endif "\"Seq #\":%d," "\"Uptime (sec)\":%lu", - BOARD_STRING, seq_nr_value, clock_seconds()); + seq_nr_value, clock_seconds()); if(len < 0 || len >= remaining) { - printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); + LOG_ERR("Buffer too short. Have %d, need %d + \\0\n", remaining, + len); return; } @@ -478,47 +489,43 @@ publish(void) memset(def_rt_str, 0, sizeof(def_rt_str)); ipaddr_sprintf(def_rt_str, sizeof(def_rt_str), uip_ds6_defrt_choose()); - len = snprintf(buf_ptr, remaining, ",\"Def Route\":\"%s\",\"RSSI (dBm)\":%d", + len = snprintf(buf_ptr, remaining, + ",\"Def Route\":\"%s\",\"RSSI (dBm)\":%d", def_rt_str, def_rt_rssi); if(len < 0 || len >= remaining) { - printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); + LOG_ERR("Buffer too short. Have %d, need %d + \\0\n", remaining, + len); return; } remaining -= len; buf_ptr += len; - len = snprintf(buf_ptr, remaining, ",\"On-Chip Temp (mC)\":%d", - cc2538_temp_sensor.value(CC2538_SENSORS_VALUE_TYPE_CONVERTED)); + for(i = 0; i < mqtt_client_extension_count; i++) { + len = snprintf(buf_ptr, remaining, ",%s", + mqtt_client_extensions[i]->value()); - if(len < 0 || len >= remaining) { - printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); - return; - } - remaining -= len; - buf_ptr += len; - - len = snprintf(buf_ptr, remaining, ",\"VDD3 (mV)\":%d", - vdd3_sensor.value(CC2538_SENSORS_VALUE_TYPE_CONVERTED)); - - if(len < 0 || len >= remaining) { - printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); - return; + if(len < 0 || len >= remaining) { + LOG_ERR("Buffer too short. Have %d, need %d + \\0\n", remaining, + len); + return; + } + remaining -= len; + buf_ptr += len; } - remaining -= len; - buf_ptr += len; len = snprintf(buf_ptr, remaining, "}}"); if(len < 0 || len >= remaining) { - printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); + LOG_ERR("Buffer too short. Have %d, need %d + \\0\n", remaining, + len); return; } mqtt_publish(&conn, NULL, pub_topic, (uint8_t *)app_buffer, strlen(app_buffer), MQTT_QOS_LEVEL_0, MQTT_RETAIN_OFF); - DBG("APP - Publish!\n"); + LOG_DBG("Publish!\n"); } /*---------------------------------------------------------------------------*/ static void @@ -548,7 +555,7 @@ state_machine(void) switch(state) { case STATE_INIT: /* If we have just been configured register MQTT connection */ - mqtt_register(&conn, &mqtt_demo_process, client_id, mqtt_event, + mqtt_register(&conn, &mqtt_client_process, client_id, mqtt_event, MAX_TCP_SEGMENT_SIZE); /* @@ -557,7 +564,7 @@ state_machine(void) */ if(strncasecmp(conf.org_id, QUICKSTART, strlen(conf.org_id)) != 0) { if(strlen(conf.auth_token) == 0) { - printf("User name set, but empty auth token\n"); + LOG_ERR("User name set, but empty auth token\n"); state = STATE_ERROR; break; } else { @@ -571,31 +578,31 @@ state_machine(void) connect_attempt = 1; state = STATE_REGISTERED; - DBG("Init\n"); + LOG_DBG("Init\n"); /* Continue */ case STATE_REGISTERED: if(uip_ds6_get_global(ADDR_PREFERRED) != NULL) { /* Registered and with a public IP. Connect */ - DBG("Registered. Connect attempt %u\n", connect_attempt); + LOG_DBG("Registered. Connect attempt %u\n", connect_attempt); ping_parent(); connect_to_broker(); } else { - leds_on(STATUS_LED); + leds_on(MQTT_CLIENT_STATUS_LED); ctimer_set(&ct, NO_NET_LED_DURATION, publish_led_off, NULL); } etimer_set(&publish_periodic_timer, NET_CONNECT_PERIODIC); return; break; case STATE_CONNECTING: - leds_on(STATUS_LED); + leds_on(MQTT_CLIENT_STATUS_LED); ctimer_set(&ct, CONNECTING_LED_DURATION, publish_led_off, NULL); /* Not connected yet. Wait */ - DBG("Connecting (%u)\n", connect_attempt); + LOG_DBG("Connecting (%u)\n", connect_attempt); break; case STATE_CONNECTED: /* Don't subscribe unless we are a registered device */ if(strncasecmp(conf.org_id, QUICKSTART, strlen(conf.org_id)) == 0) { - DBG("Using 'quickstart': Skipping subscribe\n"); + LOG_DBG("Using 'quickstart': Skipping subscribe\n"); state = STATE_PUBLISHING; } /* Continue */ @@ -615,13 +622,12 @@ state_machine(void) subscribe(); state = STATE_PUBLISHING; } else { - leds_on(STATUS_LED); + leds_on(MQTT_CLIENT_STATUS_LED); ctimer_set(&ct, PUBLISH_LED_ON_DURATION, publish_led_off, NULL); + LOG_DBG("Publishing\n"); publish(); } etimer_set(&publish_periodic_timer, conf.pub_interval); - - DBG("Publishing\n"); /* Return here so we don't end up rescheduling the timer */ return; } else { @@ -634,12 +640,12 @@ state_machine(void) * trigger a new message and we wait for TCP to either ACK the entire * packet after retries, or to timeout and notify us. */ - DBG("Publishing... (MQTT state=%d, q=%u)\n", conn.state, - conn.out_queue_full); + LOG_DBG("Publishing... (MQTT state=%d, q=%u)\n", conn.state, + conn.out_queue_full); } break; case STATE_DISCONNECTED: - DBG("Disconnected\n"); + LOG_DBG("Disconnected\n"); if(connect_attempt < RECONNECT_ATTEMPTS || RECONNECT_ATTEMPTS == RETRY_FOREVER) { /* Disconnect and backoff */ @@ -650,7 +656,7 @@ state_machine(void) interval = connect_attempt < 3 ? RECONNECT_INTERVAL << connect_attempt : RECONNECT_INTERVAL << 3; - DBG("Disconnected. Attempt %u in %lu ticks\n", connect_attempt, interval); + LOG_DBG("Disconnected. Attempt %u in %lu ticks\n", connect_attempt, interval); etimer_set(&publish_periodic_timer, interval); @@ -659,23 +665,23 @@ state_machine(void) } else { /* Max reconnect attempts reached. Enter error state */ state = STATE_ERROR; - DBG("Aborting connection after %u attempts\n", connect_attempt - 1); + LOG_DBG("Aborting connection after %u attempts\n", connect_attempt - 1); } break; case STATE_CONFIG_ERROR: /* Idle away. The only way out is a new config */ - printf("Bad configuration.\n"); + LOG_ERR("Bad configuration.\n"); return; case STATE_ERROR: default: - leds_on(STATUS_LED); + leds_on(MQTT_CLIENT_STATUS_LED); /* * 'default' should never happen. * * If we enter here it's because of some error. Stop timers. The only thing * that can bring us out is a new config event */ - printf("Default case: State=0x%02x\n", state); + LOG_ERR("Default case: State=0x%02x\n", state); return; } @@ -683,17 +689,31 @@ state_machine(void) etimer_set(&publish_periodic_timer, STATE_MACHINE_PERIODIC); } /*---------------------------------------------------------------------------*/ -PROCESS_THREAD(mqtt_demo_process, ev, data) +static void +init_extensions(void) +{ + int i; + + for(i = 0; i < mqtt_client_extension_count; i++) { + if(mqtt_client_extensions[i]->init) { + mqtt_client_extensions[i]->init(); + } + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(mqtt_client_process, ev, data) { PROCESS_BEGIN(); - printf("MQTT Demo Process\n"); + printf("MQTT Client Process\n"); if(init_config() != 1) { PROCESS_EXIT(); } + init_extensions(); + update_config(); def_rt_rssi = 0x8000000; @@ -706,7 +726,8 @@ PROCESS_THREAD(mqtt_demo_process, ev, data) PROCESS_YIELD(); - if(ev == sensors_event && data == PUBLISH_TRIGGER) { + if(ev == button_hal_release_event && + ((button_hal_button_t *)data)->unique_id == BUTTON_HAL_ID_BUTTON_ZERO) { if(state == STATE_ERROR) { connect_attempt = 1; state = STATE_REGISTERED; @@ -715,7 +736,8 @@ PROCESS_THREAD(mqtt_demo_process, ev, data) if((ev == PROCESS_EVENT_TIMER && data == &publish_periodic_timer) || ev == PROCESS_EVENT_POLL || - (ev == sensors_event && data == PUBLISH_TRIGGER)) { + (ev == button_hal_release_event && + ((button_hal_button_t *)data)->unique_id == BUTTON_HAL_ID_BUTTON_ZERO)) { state_machine(); } @@ -728,7 +750,3 @@ PROCESS_THREAD(mqtt_demo_process, ev, data) PROCESS_END(); } /*---------------------------------------------------------------------------*/ -/** - * @} - * @} - */ diff --git a/examples/mqtt-client/mqtt-client.h b/examples/mqtt-client/mqtt-client.h new file mode 100644 index 0000000000000000000000000000000000000000..c551c701b935f0ce37bcf564b5efbe323a807627 --- /dev/null +++ b/examples/mqtt-client/mqtt-client.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#ifndef MQTT_CLIENT_H_ +#define MQTT_CLIENT_H_ +/*---------------------------------------------------------------------------*/ +#include <string.h> +/*---------------------------------------------------------------------------*/ +typedef struct mqtt_client_extension_s { + void (*init)(void); + char *(*value)(void); +} mqtt_client_extension_t; +/*---------------------------------------------------------------------------*/ +#define MQTT_CLIENT_EXTENSIONS(...) \ + const mqtt_client_extension_t *mqtt_client_extensions[] = {__VA_ARGS__}; \ + const uint8_t mqtt_client_extension_count = \ + (sizeof(mqtt_client_extensions) / sizeof(mqtt_client_extensions[0])); +/*---------------------------------------------------------------------------*/ +#endif /* MQTT_CLIENT_H_ */ +/*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/cc2538-common/mqtt-demo/project-conf.h b/examples/mqtt-client/project-conf.h similarity index 85% rename from examples/platform-specific/cc2538-common/mqtt-demo/project-conf.h rename to examples/mqtt-client/project-conf.h index a3cc4073b3498c40a93d8f9305123397ed397169..7b041ae38242e40057f5ded3168e4c5c82902949 100644 --- a/examples/platform-specific/cc2538-common/mqtt-demo/project-conf.h +++ b/examples/mqtt-client/project-conf.h @@ -29,26 +29,14 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** - * \addtogroup cc2538-mqtt-demo - * @{ - * - * \file - * Project specific configuration defines for the MQTT demo - */ -/*---------------------------------------------------------------------------*/ #ifndef PROJECT_CONF_H_ #define PROJECT_CONF_H_ /*---------------------------------------------------------------------------*/ /* Enable TCP */ #define UIP_CONF_TCP 1 -/* User configuration */ -#define MQTT_DEMO_STATUS_LED LEDS_GREEN -#define MQTT_DEMO_PUBLISH_TRIGGER &button_right_sensor - /* If undefined, the demo will attempt to connect to IBM's quickstart */ -#define MQTT_DEMO_BROKER_IP_ADDR "fd00::1" +#define MQTT_CLIENT_CONF_BROKER_IP_ADDR "fd00::1" /*---------------------------------------------------------------------------*/ #endif /* PROJECT_CONF_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/examples/multicast/Makefile b/examples/multicast/Makefile index 2337ea60f2bbcc687ea5b9e52e0af5415dc89059..6037c81723c2fc21701e4e06acbf3c6700992309 100644 --- a/examples/multicast/Makefile +++ b/examples/multicast/Makefile @@ -1,8 +1,14 @@ CONTIKI_PROJECT = root intermediate sink all: $(CONTIKI_PROJECT) +# nrf52dk only supports slave mode, i.e., with no routing +PLATFORMS_EXCLUDE = nrf52dk + CONTIKI = ../.. +include $(CONTIKI)/Makefile.identify-target +MODULES_REL += $(TARGET) + MODULES += os/net/ipv6/multicast MAKE_ROUTING = MAKE_ROUTING_RPL_CLASSIC diff --git a/examples/multicast/multicast.csc b/examples/multicast/multicast.csc index e889138255cd6449d2460f935de334c00fde410e..d59708d54543fe976e3d1e8d1a4d8aa0dd2dceb5 100644 --- a/examples/multicast/multicast.csc +++ b/examples/multicast/multicast.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>Example of a uIPv6 network with multicast support</title> diff --git a/examples/multicast/project-conf.h b/examples/multicast/project-conf.h index 45fe1309ec8e6d9d9edef3864485842c09f14bd5..c1bb6910e27f0a153747858b95f31e4876865361 100644 --- a/examples/multicast/project-conf.h +++ b/examples/multicast/project-conf.h @@ -54,7 +54,12 @@ #define UIP_MCAST6_ROUTE_CONF_ROUTES 1 /* Code/RAM footprint savings so that things will fit on our device */ +#ifndef NETSTACK_MAX_ROUTE_ENTRIES #define NETSTACK_MAX_ROUTE_ENTRIES 10 +#endif + +#ifndef NBR_TABLE_CONF_MAX_NEIGHBORS #define NBR_TABLE_CONF_MAX_NEIGHBORS 10 +#endif #endif /* PROJECT_CONF_H_ */ diff --git a/examples/multicast/root.c b/examples/multicast/root.c index b4bf9dcdbaef7728be605a70bf19edfc596a0922..f997e9613f39a3fd6a1b243eae04da085e7d63e1 100644 --- a/examples/multicast/root.c +++ b/examples/multicast/root.c @@ -48,8 +48,7 @@ #define DEBUG DEBUG_PRINT #include "net/ipv6/uip-debug.h" -#include "rpl.h" -#include "rpl-dag-root.h" +#include "net/routing/routing.h" #define MAX_PAYLOAD_LEN 120 #define MCAST_SINK_UDP_PORT 3001 /* Host byte order */ @@ -84,7 +83,7 @@ multicast_send(void) PRINTF("Send to: "); PRINT6ADDR(&mcast_conn->ripaddr); PRINTF(" Remote Port %u,", uip_ntohs(mcast_conn->rport)); - PRINTF(" (msg=0x%08lx)", (unsigned long)uip_ntohl(*((uint32_t *)buf))); + PRINTF(" (msg=0x%08"PRIx32")", uip_ntohl(*((uint32_t *)buf))); PRINTF(" %lu bytes\n", (unsigned long)sizeof(id)); seq_id++; @@ -112,7 +111,7 @@ PROCESS_THREAD(rpl_root_process, ev, data) PRINTF("Multicast Engine: '%s'\n", UIP_MCAST6.name); - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_start(); prepare_mcast(); diff --git a/examples/multicast/sink.c b/examples/multicast/sink.c index e15d0f69587206e00bdd0de916d487d49eee27d4..34ad6009d78b2ad838f345e75d913ad26349f32d 100644 --- a/examples/multicast/sink.c +++ b/examples/multicast/sink.c @@ -71,7 +71,7 @@ tcpip_handler(void) if(uip_newdata()) { count++; PRINTF("In: [0x%08lx], TTL %u, total %u\n", - uip_ntohl((unsigned long) *((uint32_t *)(uip_appdata))), + (unsigned long)uip_ntohl((unsigned long) *((uint32_t *)(uip_appdata))), UIP_IP_BUF->ttl, count); } return; diff --git a/examples/multicast/srf06-cc26xx/module-macros.h b/examples/multicast/srf06-cc26xx/module-macros.h new file mode 100644 index 0000000000000000000000000000000000000000..460688ebd0aceefb0ec376505eac8a8c8722a49d --- /dev/null +++ b/examples/multicast/srf06-cc26xx/module-macros.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018, University of Bristol - http://www.bristol.ac.uk/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/* Code/RAM footprint savings so that things will fit on sensortags */ +#define NETSTACK_MAX_ROUTE_ENTRIES 4 +#define NBR_TABLE_CONF_MAX_NEIGHBORS 4 +#define QUEUEBUF_CONF_NUM 4 diff --git a/examples/multicast/zoul/module-macros.h b/examples/multicast/zoul/module-macros.h new file mode 100644 index 0000000000000000000000000000000000000000..7029c60ea13ba1e12b87ba7ab2d189de56749376 --- /dev/null +++ b/examples/multicast/zoul/module-macros.h @@ -0,0 +1,2 @@ +/* Get some extra RAM */ +#define LPM_CONF_MAX_PM 1 diff --git a/examples/nullnet/Makefile b/examples/nullnet/Makefile index 045a175cb78909cec8516a003c28f16150537555..10a113798bb7bd42b2f834e89de021d6e5046a9f 100644 --- a/examples/nullnet/Makefile +++ b/examples/nullnet/Makefile @@ -3,6 +3,8 @@ all: $(CONTIKI_PROJECT) CONTIKI = ../.. +PLATFORMS_EXCLUDE = nrf52dk + #use this to enable TSCH: MAKE_MAC = MAKE_MAC_TSCH MAKE_MAC ?= MAKE_MAC_CSMA MAKE_NET = MAKE_NET_NULLNET diff --git a/examples/nullnet/nullnet-broadcast.c b/examples/nullnet/nullnet-broadcast.c index d654784ebbfb394b3526d3b00a87bfbbc3c62ac7..7bb1f1c870b7363278e8b2c229df96d72084c61f 100644 --- a/examples/nullnet/nullnet-broadcast.c +++ b/examples/nullnet/nullnet-broadcast.c @@ -65,9 +65,13 @@ AUTOSTART_PROCESSES(&nullnet_example_process); void input_callback(const void *data, uint16_t len, const linkaddr_t *src, const linkaddr_t *dest) { - LOG_INFO("Received %u from ", *(unsigned *)data); - LOG_INFO_LLADDR(src); - LOG_INFO_("\n"); + if(len == sizeof(unsigned)) { + unsigned count; + memcpy(&count, data, sizeof(count)); + LOG_INFO("Received %u from ", count); + LOG_INFO_LLADDR(src); + LOG_INFO_("\n"); + } } /*---------------------------------------------------------------------------*/ PROCESS_THREAD(nullnet_example_process, ev, data) diff --git a/examples/nullnet/nullnet-broadcast.csc b/examples/nullnet/nullnet-broadcast.csc index 0542bfc977cd832c1783fe2e30d757ae777ce65e..6168455256172ae9a702c3c4ccbd54590c2a0c5e 100644 --- a/examples/nullnet/nullnet-broadcast.csc +++ b/examples/nullnet/nullnet-broadcast.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>NullNet Broadcast Example</title> diff --git a/examples/nullnet/nullnet-unicast.c b/examples/nullnet/nullnet-unicast.c index 98866f381a25448a77612908a9436ebf50be1418..5dd9d9fcd3569f8ce87670759c87da7c5bc70369 100644 --- a/examples/nullnet/nullnet-unicast.c +++ b/examples/nullnet/nullnet-unicast.c @@ -67,9 +67,13 @@ AUTOSTART_PROCESSES(&nullnet_example_process); void input_callback(const void *data, uint16_t len, const linkaddr_t *src, const linkaddr_t *dest) { - LOG_INFO("Received %u from ", *(unsigned *)data); - LOG_INFO_LLADDR(src); - LOG_INFO_("\n"); + if(len == sizeof(unsigned)) { + unsigned count; + memcpy(&count, data, sizeof(count)); + LOG_INFO("Received %u from ", count); + LOG_INFO_LLADDR(src); + LOG_INFO_("\n"); + } } /*---------------------------------------------------------------------------*/ PROCESS_THREAD(nullnet_example_process, ev, data) diff --git a/examples/nullnet/nullnet-unicast.csc b/examples/nullnet/nullnet-unicast.csc index d756d9892695c8e2a3df13fd8d12704d9d7b7d8f..5a93836cd5056a8e2aea97e23271e47ad49b801e 100644 --- a/examples/nullnet/nullnet-unicast.csc +++ b/examples/nullnet/nullnet-unicast.csc @@ -4,10 +4,9 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> - <title>NullNet Broadcast Example</title> + <title>NullNet Unicast Example</title> <randomseed>123456</randomseed> <motedelay_us>1000000</motedelay_us> <radiomedium> @@ -24,8 +23,8 @@ org.contikios.cooja.contikimote.ContikiMoteType <identifier>mtype634</identifier> <description>Cooja Mote Type #1</description> - <source>[CONTIKI_DIR]/examples/nullnet/nullnet-broadcast.c</source> - <commands>make nullnet-broadcast.cooja TARGET=cooja</commands> + <source>[CONTIKI_DIR]/examples/nullnet/nullnet-unicast.c</source> + <commands>make nullnet-unicast.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -176,4 +175,3 @@ <location_y>408</location_y> </plugin> </simconf> - diff --git a/examples/platform-specific/cc2538-common/Makefile b/examples/platform-specific/cc2538-common/Makefile index 70ef1bc3f2361d50645b91ef115d677f1cb0edfa..c55c65eafba5fe747887f5bb1b96fad077c4da99 100644 --- a/examples/platform-specific/cc2538-common/Makefile +++ b/examples/platform-specific/cc2538-common/Makefile @@ -2,5 +2,7 @@ CONTIKI_PROJECT = test-pwm timer-test test-uart all: $(CONTIKI_PROJECT) +PLATFORMS_ONLY = cc2538dk openmote-cc2538 zoul + CONTIKI = ../../.. include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/cc2538-common/crypto/Makefile b/examples/platform-specific/cc2538-common/crypto/Makefile index b621dac955e7b9f0ae746d79191740cc827c7dae..2191d44f04ed127ec6c19ed8dbe1bf6226194880 100644 --- a/examples/platform-specific/cc2538-common/crypto/Makefile +++ b/examples/platform-specific/cc2538-common/crypto/Makefile @@ -3,5 +3,7 @@ CONTIKI_PROJECT += sha256-test all: $(CONTIKI_PROJECT) +PLATFORMS_ONLY = cc2538dk openmote-cc2538 zoul + CONTIKI = ../../../.. include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/cc2538-common/mqtt-demo/Makefile b/examples/platform-specific/cc2538-common/mqtt-demo/Makefile deleted file mode 100644 index 1295da093e4c5848438e76b66a3fe404145fb43f..0000000000000000000000000000000000000000 --- a/examples/platform-specific/cc2538-common/mqtt-demo/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: mqtt-demo - - -MODULES += os/net/app-layer/mqtt - -CONTIKI = ../../../.. -include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/cc2538-common/mqtt-demo/Makefile.target b/examples/platform-specific/cc2538-common/mqtt-demo/Makefile.target deleted file mode 100644 index 777593c88def5c04f06032bba5ea47bf4b1832cf..0000000000000000000000000000000000000000 --- a/examples/platform-specific/cc2538-common/mqtt-demo/Makefile.target +++ /dev/null @@ -1 +0,0 @@ -TARGET = cc2538dk diff --git a/examples/platform-specific/cc2538-common/pka/Makefile b/examples/platform-specific/cc2538-common/pka/Makefile index 488e27db999ebcb245489538b09d19def7285409..01ba6fe6219e8656553ae35cd1a81700ec7b27c6 100644 --- a/examples/platform-specific/cc2538-common/pka/Makefile +++ b/examples/platform-specific/cc2538-common/pka/Makefile @@ -2,5 +2,7 @@ CONTIKI_PROJECT = ecc-ecdh ecc-sign ecc-verify all: $(CONTIKI_PROJECT) +PLATFORMS_ONLY = cc2538dk openmote-cc2538 zoul + CONTIKI = ../../../.. include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/cc26xx/Makefile b/examples/platform-specific/cc26xx/Makefile index 80506b26b57e8cc7207b72bb4358955bf8b1e7a3..40e484bcc71dd25c4069b5dcf1e357f68279dd99 100644 --- a/examples/platform-specific/cc26xx/Makefile +++ b/examples/platform-specific/cc26xx/Makefile @@ -1,5 +1,7 @@ CONTIKI_PROJECT = cc26xx-demo +PLATFORMS_ONLY = srf06-cc26xx + all: $(CONTIKI_PROJECT) CONTIKI = ../../.. diff --git a/examples/platform-specific/cc26xx/ble-ipv6/Makefile b/examples/platform-specific/cc26xx/ble-ipv6/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..4ba928ad3fa1280cfb8070ed691a54c2e636d5ed --- /dev/null +++ b/examples/platform-specific/cc26xx/ble-ipv6/Makefile @@ -0,0 +1,11 @@ +CONTIKI_PROJECT=client + +all: $(CONTIKI_PROJECT) + +PLATFORMS_ONLY = srf06-cc26xx +BOARDS_ONLY = launchpad/cc2650 sensortag/cc2650 srf06/cc26xx + +MAKE_MAC = MAKE_MAC_BLE +MAKE_NET = MAKE_NET_IPV6 +CONTIKI = ../../../.. +include $(CONTIKI)/Makefile.include \ No newline at end of file diff --git a/examples/platform-specific/cc26xx/ble-ipv6/README.md b/examples/platform-specific/cc26xx/ble-ipv6/README.md new file mode 100644 index 0000000000000000000000000000000000000000..d33c7329f393ef8c427c29f09e9c8c22c366248b --- /dev/null +++ b/examples/platform-specific/cc26xx/ble-ipv6/README.md @@ -0,0 +1,80 @@ +# BLEach: a fully open-source IPv6-over-BLE stack for Constrained Embedded IoT Devices + +## Overview +In 2015, the IETF released the [RFC 7668][rfc7668] that specifies how IPv6 packets +can be exchanged using BLE connections (IPv6 over BLE). +This Contiki extenstion implements [BLEach][bleachWeb], a fully open-source IPv6-over-BLE stack for Contiki. +BLEach in Contiki-NG can be used for node (BLE slave) devices. + +It was developed by +* [Michael Spoerk](http://www.michaelspoerk.com), Graz University of Technology, michael.spoerk@tugraz.at, github user: [spoerk](https://github.com/spoerk) + +This IPv6-over-BLE stack is presented and evaluated in the paper: +[BLEach: Exploiting the Full Potential of IPv6 over BLE in Constrained Embedded IoT Devices](http://sensys.acm.org/2017/), ACM SenSys'17. + +## Features +This implementation includes: + * IPv6-over-BLE node implementation compliant to [RFC 7668][rfc7668] + * connect to a single IPv6-over-BLE border router + * maximum IPv6 packet length of 1280 bytes + * BLE L2CAP channels in LE credit-based flow control mode + * BLE link layer support for version [4.1][bleSpec]: + * BLE advertisement + * BLE connection slave + +It has been tested on the TI CC2650 SensorTag and the TI CC2650 LaunchPad hardware. + +## Modules +The IPv6-over-BLE stack comes with the following modules: + +### BLE radio +The implementation of the BLE radio for the TI CC26xx platform is implemented in `arch/cpu/cc26xx-cc13xx/rf-core/ble-cc2650.c` +and `arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/*.[ch]`. +These files contain all the hardware specific code for supporting BLE as a link layer. + +### BLE L2CAP layer +The L2CAP LE credit-based flow control support is implemented in `arch/cpu/cc26xx-cc13xx/rf-core/ble-l2cap.c`. +Besides implementing rudimentary L2CAP support, this module handles fragmentation of large IPv6 packets. + +## Using BLEach +Currently, BLEach is only available for the Texas Instruments CC2650 hardware platform. + +The following sections describe how to configure BLEach for IPv6-over-BLE nodes and border routers. + +### IPv6-over-BLE node (BLE slave) +To enable IPv6 over BLE, the project conf needs to contain: +``` +#define PACKETBUF_CONF_SIZE 1280 +#define QUEUEBUF_CONF_NUM 1 +#define UIP_CONF_BUFFER_SIZE 1280 + +#define NETSTACK_CONF_RADIO ble_cc2650_driver +#define NETSTACK_CONF_MAC ble_l2cap_driver + +#define RTIMER_CONF_MULTIPLE_ACCESS 1 + +/* 6LoWPAN settings */ +#define SICSLOWPAN_CONF_MAC_MAX_PAYLOAD 1280 +#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 +#define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD 0 /* always use compression */ +#define SICSLOWPAN_CONF_FRAG 0 +#define SICSLOWPAN_FRAMER_HDRLEN 0 + +/* network stack settings */ +#define UIP_CONF_ROUTER 0 +#define UIP_CONF_ND6_SEND_NA 1 + +``` + +The following optional parameter can be used to configure that BLE advertisement behaviour: +``` +#define BLE_CONF_DEVICE_NAME "TI CC26xx device" +#define BLE_CONF_ADV_INTERVAL 25 +``` +`BLE_CONF_DEVICE_NAME` holds the device name that is used for advertisement, `BLE_CONF_ADV_INTERVAL` +specifies the used advertisement interval in milliseconds. + + +[rfc7668]: https://tools.ietf.org/html/rfc7668 +[bleSpec]: https://www.bluetooth.com/specifications/bluetooth-core-specification/legacy-specifications +[bleachWeb]: http://www.iti.tugraz.at/BLEach diff --git a/examples/platform-specific/cc26xx/ble-ipv6/client.c b/examples/platform-specific/cc26xx/ble-ipv6/client.c new file mode 100644 index 0000000000000000000000000000000000000000..79878cf3112c7ed8fadc10cd2ca56aefb4f332d2 --- /dev/null +++ b/examples/platform-specific/cc26xx/ble-ipv6/client.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2017, Graz University of Technology + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * A simple IPv6-over-BLE UDP-client. + * + * \author + * Michael Spoerk <michael.spoerk@tugraz.at> + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" + +#include "net/ipv6/uip-icmp6.h" + +#include <string.h> +#include <stdio.h> + +#include "os/dev/ble-hal.h" +/*---------------------------------------------------------------------------*/ +#define SERVER_IP "::" +#define CLIENT_PORT 61617 +#define SERVER_PORT 61616 + +#define PING_TIMEOUT (CLOCK_SECOND / 4) +#define CLIENT_SEND_INTERVAL (CLOCK_SECOND * 1) + +#define UDP_LEN_MAX 255 +/*---------------------------------------------------------------------------*/ +static uip_ipaddr_t server_addr; +static struct uip_icmp6_echo_reply_notification icmp_notification; +static uint8_t echo_received; +static struct uip_udp_conn *conn; + +static struct etimer timer; +static char buf[UDP_LEN_MAX]; +static uint16_t packet_counter; +/*---------------------------------------------------------------------------*/ +PROCESS(ipv6_ble_client_process, "IPv6 over BLE - client process"); +AUTOSTART_PROCESSES(&ipv6_ble_client_process); +/*---------------------------------------------------------------------------*/ +void +icmp_reply_handler(uip_ipaddr_t *source, uint8_t ttl, + uint8_t *data, uint16_t datalen) +{ + if(uip_ip6addr_cmp(source, &server_addr)) { + printf("echo response received\n"); + echo_received = 1; + } +} +/*---------------------------------------------------------------------------*/ +static void +tcpip_handler(void) +{ + char data[UDP_LEN_MAX]; + if(uip_newdata()) { + strncpy(data, uip_appdata, uip_datalen()); + data[uip_datalen()] = '\0'; + printf("rec. message: <%s>\n", data); + } +} +/*---------------------------------------------------------------------------*/ +static void +timeout_handler(void) +{ + sprintf(buf, "Hello server %04u!", packet_counter); + printf("send message: <%s>\n", buf); + uip_udp_packet_send(conn, buf, strlen(buf)); + packet_counter++; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(ipv6_ble_client_process, ev, data) +{ + PROCESS_BEGIN(); + printf("IPv6-over-BLE client started\n"); + + uiplib_ipaddrconv(SERVER_IP, &server_addr); + uip_icmp6_echo_reply_callback_add(&icmp_notification, icmp_reply_handler); + + printf("pinging the IPv6-over-BLE server\n"); + + do { + etimer_set(&timer, PING_TIMEOUT); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer)); + uip_icmp6_send(&server_addr, ICMP6_ECHO_REQUEST, 0, 20); + } while(!echo_received); + + conn = udp_new(&server_addr, UIP_HTONS(SERVER_PORT), NULL); + udp_bind(conn, UIP_HTONS(CLIENT_PORT)); + + etimer_set(&timer, CLIENT_SEND_INTERVAL); + + while(1) { + PROCESS_YIELD(); + if((ev == PROCESS_EVENT_TIMER) && (data == &timer)) { + timeout_handler(); + etimer_set(&timer, CLIENT_SEND_INTERVAL); + } else if(ev == tcpip_event) { + tcpip_handler(); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/cc26xx/ble-ipv6/project-conf.h b/examples/platform-specific/cc26xx/ble-ipv6/project-conf.h new file mode 100644 index 0000000000000000000000000000000000000000..815cfb90a0dd6ab6cde795197b086b152bfe7c63 --- /dev/null +++ b/examples/platform-specific/cc26xx/ble-ipv6/project-conf.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, Graz University of Technology + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \author + * Michael Spoerk <michael.spoerk@tugraz.at> + */ +/*---------------------------------------------------------------------------*/ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +/*---------------------------------------------------------------------------*/ +/* Disable button shutdown functionality */ +#define BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN 0 +/*---------------------------------------------------------------------------*/ +/* Change to match your configuration */ +#define BOARD_CONF_DEBUGGER_DEVPACK 1 +/*---------------------------------------------------------------------------*/ +#define PACKETBUF_CONF_SIZE 1280 +#define QUEUEBUF_CONF_NUM 1 +#define UIP_CONF_BUFFER_SIZE 1280 + +#define NETSTACK_CONF_RADIO ble_cc2650_driver + +#define LOG_CONF_LEVEL_MAC LOG_LEVEL_INFO + +/* BLE L2CAP settings */ +#define BLE_CONF_DEVICE_NAME "TI CC26xx device" +#define BLE_CONF_ADV_INTERVAL 25 + +/*/ * 6LoWPAN settings * / */ +#define SICSLOWPAN_CONF_MAC_MAX_PAYLOAD 1280 +#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_6LORH +#define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD 0 /* always use compression */ +#define SICSLOWPAN_CONF_FRAG 0 +#define SICSLOWPAN_FRAMER_HDRLEN 0 +/* */ +/*/ * network stack settings * / */ +#define UIP_CONF_ROUTER 0 +#define UIP_CONF_ND6_SEND_NA 1 +/*---------------------------------------------------------------------------*/ +#endif /* PROJECT_CONF_H_ */ +/*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/cc26xx/cc26xx-demo.c b/examples/platform-specific/cc26xx/cc26xx-demo.c index f5045a5bde9feeb43122e77c5e089c92fdca6281..8c90905af8bcd11c139878c6cb54fe28789acab9 100644 --- a/examples/platform-specific/cc26xx/cc26xx-demo.c +++ b/examples/platform-specific/cc26xx/cc26xx-demo.c @@ -62,8 +62,8 @@ * - sensors : Some sensortag sensors are read asynchronously (see sensor * documentation). For those, this example will print out * readings in a staggered fashion at a random interval - * - Buttons : CC26XX_DEMO_SENSOR_1 button will toggle CC26XX_DEMO_LEDS_BUTTON - * - CC26XX_DEMO_SENSOR_2 turns on LEDS_REBOOT and causes a + * - Buttons : CC26XX_DEMO_TRIGGER_1 button will toggle CC26XX_DEMO_LEDS_BUTTON + * - CC26XX_DEMO_TRIGGER_2 turns on LEDS_REBOOT and causes a * watchdog reboot * - The remaining buttons will just print something * - The example also shows how to retrieve the duration of a @@ -81,6 +81,7 @@ #include "sys/ctimer.h" #include "dev/leds.h" #include "dev/watchdog.h" +#include "dev/button-hal.h" #include "random.h" #include "button-sensor.h" #include "batmon-sensor.h" @@ -97,23 +98,11 @@ #define CC26XX_DEMO_LEDS_BUTTON LEDS_RED #define CC26XX_DEMO_LEDS_REBOOT LEDS_ALL /*---------------------------------------------------------------------------*/ -#define CC26XX_DEMO_SENSOR_NONE (void *)0xFFFFFFFF - -#define CC26XX_DEMO_SENSOR_1 &button_left_sensor -#define CC26XX_DEMO_SENSOR_2 &button_right_sensor +#define CC26XX_DEMO_TRIGGER_1 BOARD_BUTTON_HAL_INDEX_KEY_LEFT +#define CC26XX_DEMO_TRIGGER_2 BOARD_BUTTON_HAL_INDEX_KEY_RIGHT #if BOARD_SENSORTAG -#define CC26XX_DEMO_SENSOR_3 CC26XX_DEMO_SENSOR_NONE -#define CC26XX_DEMO_SENSOR_4 CC26XX_DEMO_SENSOR_NONE -#define CC26XX_DEMO_SENSOR_5 &reed_relay_sensor -#elif BOARD_LAUNCHPAD -#define CC26XX_DEMO_SENSOR_3 CC26XX_DEMO_SENSOR_NONE -#define CC26XX_DEMO_SENSOR_4 CC26XX_DEMO_SENSOR_NONE -#define CC26XX_DEMO_SENSOR_5 CC26XX_DEMO_SENSOR_NONE -#else -#define CC26XX_DEMO_SENSOR_3 &button_up_sensor -#define CC26XX_DEMO_SENSOR_4 &button_down_sensor -#define CC26XX_DEMO_SENSOR_5 &button_select_sensor +#define CC26XX_DEMO_TRIGGER_3 BOARD_BUTTON_HAL_INDEX_REED_RELAY #endif /*---------------------------------------------------------------------------*/ static struct etimer et; @@ -343,10 +332,6 @@ get_sync_sensor_readings(void) static void init_sensors(void) { -#if BOARD_SENSORTAG - SENSORS_ACTIVATE(reed_relay_sensor); -#endif - SENSORS_ACTIVATE(batmon_sensor); } /*---------------------------------------------------------------------------*/ @@ -392,46 +377,41 @@ PROCESS_THREAD(cc26xx_demo_process, ev, data) etimer_set(&et, CC26XX_DEMO_LOOP_INTERVAL); } - } else if(ev == sensors_event) { - if(data == CC26XX_DEMO_SENSOR_1) { - printf("Left: Pin %d, press duration %d clock ticks\n", - (CC26XX_DEMO_SENSOR_1)->value(BUTTON_SENSOR_VALUE_STATE), - (CC26XX_DEMO_SENSOR_1)->value(BUTTON_SENSOR_VALUE_DURATION)); - - if((CC26XX_DEMO_SENSOR_1)->value(BUTTON_SENSOR_VALUE_DURATION) > - CLOCK_SECOND) { - printf("Long button press!\n"); - } + } else if(ev == button_hal_periodic_event) { + button_hal_button_t *button = data; + + printf("%s periodic event, duration %d seconds\n", + BUTTON_HAL_GET_DESCRIPTION(button), + button->press_duration_seconds); + } else if(ev == button_hal_release_event) { + button_hal_button_t *btn = (button_hal_button_t *)data; + + printf("%s release event\n", BUTTON_HAL_GET_DESCRIPTION(btn)); + if(btn->unique_id== CC26XX_DEMO_TRIGGER_1) { leds_toggle(CC26XX_DEMO_LEDS_BUTTON); - } else if(data == CC26XX_DEMO_SENSOR_2) { + } else if(btn->unique_id == CC26XX_DEMO_TRIGGER_2) { leds_on(CC26XX_DEMO_LEDS_REBOOT); watchdog_reboot(); - } else if(data == CC26XX_DEMO_SENSOR_3) { - printf("Up\n"); - } else if(data == CC26XX_DEMO_SENSOR_4) { - printf("Down\n"); - } else if(data == CC26XX_DEMO_SENSOR_5) { #if BOARD_SENSORTAG + } else if(btn->unique_id == CC26XX_DEMO_TRIGGER_3) { if(buzzer_state()) { buzzer_stop(); } else { buzzer_start(1000); } - } else if(ev == sensors_event && data == &bmp_280_sensor) { + } + } else if(ev == sensors_event) { + if(data == &bmp_280_sensor) { get_bmp_reading(); - } else if(ev == sensors_event && data == &opt_3001_sensor) { + } else if(data == &opt_3001_sensor) { get_light_reading(); - } else if(ev == sensors_event && data == &hdc_1000_sensor) { + } else if(data == &hdc_1000_sensor) { get_hdc_reading(); - } else if(ev == sensors_event && data == &tmp_007_sensor) { + } else if(data == &tmp_007_sensor) { get_tmp_reading(); - } else if(ev == sensors_event && data == &mpu_9250_sensor) { + } else if(data == &mpu_9250_sensor) { get_mpu_reading(); -#elif BOARD_SMARTRF06EB - printf("Sel: Pin %d, press duration %d clock ticks\n", - button_select_sensor.value(BUTTON_SENSOR_VALUE_STATE), - button_select_sensor.value(BUTTON_SENSOR_VALUE_DURATION)); #endif } } diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/Makefile b/examples/platform-specific/cc26xx/cc26xx-web-demo/Makefile index 88b4b018488d89d0fd6be20a38d592e01fcc93e9..05dbface10a5da1cd3c5a6400289326591faf3ca 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/Makefile +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/Makefile @@ -1,16 +1,18 @@ -all: cc26xx-web-demo +CONTIKI_PROJECT = cc26xx-web-demo +all: $(CONTIKI_PROJECT) -REST_RESOURCES_DIR = ./resources +PLATFORMS_ONLY = srf06-cc26xx -REST_RESOURCES_FILES += res-leds.c res-toggle-leds.c res-device.c -REST_RESOURCES_FILES += res-sensors.c res-ble-advd.c res-net.c +MODULES_REL += ./resources -PROJECTDIRS += $(REST_RESOURCES_DIR) -PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES) - -PROJECT_SOURCEFILES += cetic-6lbr-client.c coap-server.c net-uart.c mqtt-client.c +PROJECT_SOURCEFILES += coap-server.c net-uart.c mqtt-client.c PROJECT_SOURCEFILES += httpd-simple.c +ifeq ($(MAKE_ROUTING),MAKE_ROUTING_RPL_CLASSIC) +# 6lbr only supports RPL Classic +PROJECT_SOURCEFILES += cetic-6lbr-client.c +endif + # REST Engine shall use Erbium CoAP implementation MODULES += os/net/app-layer/mqtt MODULES += os/net/app-layer/coap diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/README.md b/examples/platform-specific/cc26xx/cc26xx-web-demo/README.md index 67b28ba93225c2b8d3ed4bb0dfc9f3c0716554bb..6acd69b3a2346966de18ad09d9359e49923f0f79 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/README.md +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/README.md @@ -54,33 +54,38 @@ tab, as per the image below. CoAP Server ----------- -For this functionality to work, you will need to install the -[Copper (Cu)](https://addons.mozilla.org/en-US/firefox/addon/copper-270430/) -addon to your browser. +For this functionality to work, you will need to install a CoAP client. +You can achieve this by following the guides on how to set up your system +[in the wiki](https://github.com/contiki-ng/contiki-ng/wiki#setting-up-contiki-ng). -From the sensors tab in the 6lbr web page, click the 'coap' link in the line -corresponding to your CC26xx device. Once the addon fires up, select -".well-known/core" in the left pane and then hit the 'Get' button at the top. +You should start by sending a CoAP GET request for the `.well-known/core` +resource. If you are using libcoap's CoAP client, this can be achieved by: - +``` +coap-client -m get coap://[<device IPv6 address here>]/.well-known/core +``` + +Adjust the above command to match the command line arguments of your CoAP +client. The Device will respond with a list of all available CoAP resources. This list -will be different between the Srf and the SensorTag. The screenshot below shows -a (partial) list of resources exported by the SensorTag CoAP server. Select -a resource on the left pane and hit 'Get' to retrieve its value. Select -`lt/g` and hit 'Post' to toggle the green LED, `lt/r` for the red one. +will be different between the various CC13x0/CC26x0 boards. + +Send a CoAP GET request for any of those resrouces to retrieve its value. + +Send a CoAP POST to the `lt/g` or `lt/r` to toggle the green/red LED +respectively. -You can also use CoAP to enable/disable BLE advertisements! Select -`dev/ble_advd` and then hit the "Outgoing" button in the payload panel. Type in -the desired payload, which can be: +You can also use CoAP to enable/disable BLE advertisements! This can be done +by sending a PUT or POST request to the `dev/ble_advd` resource. Your request +should contain the desired payload, which can be: * `mode=on|off` * `name=<name>` * `interval=<secs>` -or a combination of both delimited with an amp. For example, you can set as -payload `mode=on&name=My CC26xx Device 4&interval=5`. Once you have set the -payload, hit either the POST or PUT button. +or a combination of the above delimited with an amp. For example, you can set +as payload `mode=on&name=My CC26xx Device 4&interval=5`. Bear in mind that you must set `name` at least once before enabling BLE advertisements. If you fail to do so, the RF will refuse to enter BLE mode and diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c index e14991d04f8738f80fdf114cc26418fa56d9c2a0..f69a194782815f22ad2bd1845586386544e91d8f 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c @@ -39,13 +39,13 @@ /*---------------------------------------------------------------------------*/ #include "contiki.h" #include "contiki-net.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "board-peripherals.h" #include "lib/sensors.h" #include "lib/list.h" #include "sys/process.h" #include "net/ipv6/sicslowpan.h" -#include "button-sensor.h" +#include "dev/button-hal.h" #include "batmon-sensor.h" #include "httpd-simple.h" #include "cc26xx-web-demo.h" @@ -55,6 +55,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <strings.h> #include "ti-lib.h" /*---------------------------------------------------------------------------*/ @@ -194,15 +195,15 @@ save_config() int rv; cc26xx_web_demo_sensor_reading_t *reading = NULL; - rv = ext_flash_open(); + rv = ext_flash_open(NULL); if(!rv) { printf("Could not open flash to save config\n"); - ext_flash_close(); + ext_flash_close(NULL); return; } - rv = ext_flash_erase(CONFIG_FLASH_OFFSET, sizeof(cc26xx_web_demo_config_t)); + rv = ext_flash_erase(NULL, CONFIG_FLASH_OFFSET, sizeof(cc26xx_web_demo_config_t)); if(!rv) { printf("Error erasing flash\n"); @@ -219,14 +220,14 @@ save_config() } } - rv = ext_flash_write(CONFIG_FLASH_OFFSET, sizeof(cc26xx_web_demo_config_t), + rv = ext_flash_write(NULL, CONFIG_FLASH_OFFSET, sizeof(cc26xx_web_demo_config_t), (uint8_t *)&cc26xx_web_demo_config); if(!rv) { printf("Error saving config\n"); } } - ext_flash_close(); + ext_flash_close(NULL); #endif } /*---------------------------------------------------------------------------*/ @@ -238,18 +239,18 @@ load_config() cc26xx_web_demo_config_t tmp_cfg; cc26xx_web_demo_sensor_reading_t *reading = NULL; - int rv = ext_flash_open(); + int rv = ext_flash_open(NULL); if(!rv) { printf("Could not open flash to load config\n"); - ext_flash_close(); + ext_flash_close(NULL); return; } - rv = ext_flash_read(CONFIG_FLASH_OFFSET, sizeof(tmp_cfg), + rv = ext_flash_read(NULL, CONFIG_FLASH_OFFSET, sizeof(tmp_cfg), (uint8_t *)&tmp_cfg); - ext_flash_close(); + ext_flash_close(NULL); if(!rv) { printf("Error loading config\n"); @@ -881,8 +882,6 @@ init_sensors(void) list_add(sensor_list, &mpu_gyro_x_reading); list_add(sensor_list, &mpu_gyro_y_reading); list_add(sensor_list, &mpu_gyro_z_reading); - - SENSORS_ACTIVATE(reed_relay_sensor); #endif } /*---------------------------------------------------------------------------*/ @@ -976,16 +975,16 @@ PROCESS_THREAD(cc26xx_web_demo_process, ev, data) } #endif - if(ev == sensors_event && data == CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER) { - if((CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER)->value( - BUTTON_SENSOR_VALUE_DURATION) > CLOCK_SECOND * 5) { - printf("Restoring defaults!\n"); - cc26xx_web_demo_restore_defaults(); - } else { - init_sensor_readings(); - - process_post(PROCESS_BROADCAST, cc26xx_web_demo_publish_event, NULL); - } + if(ev == button_hal_release_event && + ((button_hal_button_t *)data)->unique_id == + CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER) { + init_sensor_readings(); + process_post(PROCESS_BROADCAST, cc26xx_web_demo_publish_event, NULL); + } else if(ev == button_hal_periodic_event && + ((button_hal_button_t *)data)->unique_id == + CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER) { + printf("Restoring defaults!\n"); + cc26xx_web_demo_restore_defaults(); } else if(ev == httpd_simple_event_new_config) { save_config(); #if BOARD_SENSORTAG diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h b/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h index e40cd1864ed3f79c4b7e16edd1fb25cb153659f2..0761725c7a38ae194fdc14372ae1e4d9073326eb 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h @@ -98,18 +98,18 @@ /*---------------------------------------------------------------------------*/ /* User configuration */ /* Take a sensor reading on button press */ -#define CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER &button_left_sensor +#define CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER BOARD_BUTTON_HAL_INDEX_KEY_LEFT /* Payload length of ICMPv6 echo requests used to measure RSSI with def rt */ #define CC26XX_WEB_DEMO_ECHO_REQ_PAYLOAD_LEN 20 #if BOARD_SENSORTAG /* Force an MQTT publish on sensor event */ -#define CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER &reed_relay_sensor +#define CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER BOARD_BUTTON_HAL_INDEX_REED_RELAY #elif BOARD_LAUNCHPAD -#define CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER &button_left_sensor +#define CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER BOARD_BUTTON_HAL_INDEX_KEY_LEFT #else -#define CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER &button_down_sensor +#define CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER BOARD_BUTTON_HAL_INDEX_KEY_DOWN #endif #define CC26XX_WEB_DEMO_STATUS_LED LEDS_GREEN diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/cetic-6lbr-client.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/cetic-6lbr-client.c index e12f2cd16cbf3519945ceb4a56bbeae09370d637..569a36a89024ef711a82f2cd605d339aae6c0eaf 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/cetic-6lbr-client.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/cetic-6lbr-client.c @@ -35,8 +35,14 @@ #include "contiki.h" #include "contiki-lib.h" #include "contiki-net.h" -#include "rpl.h" +#include "net/routing/routing.h" #include "net/ipv6/uip.h" +#if ROUTING_CONF_RPL_CLASSIC +#include "net/routing/rpl-classic/rpl.h" +#include "net/routing/rpl-classic/rpl-private.h" +#else +#error The 6LBR client is only meant for RPL Classic. Set MAKE_ROUTING accordingly. +#endif #include <string.h> #include <stdio.h> @@ -155,8 +161,8 @@ timeout_handler(void) PRINT6ADDR(&client_conn->ripaddr); i = sprintf(buf, "%d | ", ++seq_id); instance = rpl_get_default_instance(); - if(instance && instance->dag.preferred_parent) { - add_ipaddr(buf + i, rpl_parent_get_ipaddr(instance->dag.preferred_parent)); + if(instance && instance->current_dag->preferred_parent) { + add_ipaddr(buf + i, rpl_parent_get_ipaddr(instance->current_dag->preferred_parent)); } else { sprintf(buf + i, "(null)"); } diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.c index 8897eb23f5a9802f34c384829d4ca2b8652ba38a..54289f1027de2e0f4138d45829dd1ef549513ac7 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.c @@ -37,7 +37,7 @@ /*---------------------------------------------------------------------------*/ #include "contiki.h" #include "contiki-net.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "board-peripherals.h" #include "rf-core/rf-ble.h" #include "cc26xx-web-demo.h" @@ -47,48 +47,48 @@ #include <string.h> /*---------------------------------------------------------------------------*/ /* Common resources */ -extern resource_t res_leds; +extern coap_resource_t res_leds; -extern resource_t res_batmon_temp; -extern resource_t res_batmon_volt; +extern coap_resource_t res_batmon_temp; +extern coap_resource_t res_batmon_volt; -extern resource_t res_device_sw; -extern resource_t res_device_hw; -extern resource_t res_device_uptime; -extern resource_t res_device_cfg_reset; +extern coap_resource_t res_device_sw; +extern coap_resource_t res_device_hw; +extern coap_resource_t res_device_uptime; +extern coap_resource_t res_device_cfg_reset; -extern resource_t res_parent_rssi; -extern resource_t res_parent_ip; +extern coap_resource_t res_parent_rssi; +extern coap_resource_t res_parent_ip; #if RF_BLE_ENABLED -extern resource_t res_ble_advd; +extern coap_resource_t res_ble_advd; #endif -extern resource_t res_toggle_red; -extern resource_t res_toggle_green; +extern coap_resource_t res_toggle_red; +extern coap_resource_t res_toggle_green; /* Board-specific resources */ #if BOARD_SENSORTAG -extern resource_t res_bmp280_temp; -extern resource_t res_bmp280_press; -extern resource_t res_tmp007_amb; -extern resource_t res_tmp007_obj; -extern resource_t res_hdc1000_temp; -extern resource_t res_hdc1000_hum; -extern resource_t res_opt3001_light; -extern resource_t res_mpu_acc_x; -extern resource_t res_mpu_acc_y; -extern resource_t res_mpu_acc_z; -extern resource_t res_mpu_gyro_x; -extern resource_t res_mpu_gyro_y; -extern resource_t res_mpu_gyro_z; +extern coap_resource_t res_bmp280_temp; +extern coap_resource_t res_bmp280_press; +extern coap_resource_t res_tmp007_amb; +extern coap_resource_t res_tmp007_obj; +extern coap_resource_t res_hdc1000_temp; +extern coap_resource_t res_hdc1000_hum; +extern coap_resource_t res_opt3001_light; +extern coap_resource_t res_mpu_acc_x; +extern coap_resource_t res_mpu_acc_y; +extern coap_resource_t res_mpu_acc_z; +extern coap_resource_t res_mpu_gyro_x; +extern coap_resource_t res_mpu_gyro_y; +extern coap_resource_t res_mpu_gyro_z; #else -extern resource_t res_toggle_orange; -extern resource_t res_toggle_yellow; +extern coap_resource_t res_toggle_orange; +extern coap_resource_t res_toggle_yellow; #endif #if CC26XX_WEB_DEMO_ADC_DEMO -extern resource_t res_adc_dio23; +extern coap_resource_t res_adc_dio23; #endif /*---------------------------------------------------------------------------*/ const char *coap_server_not_found_msg = "Resource not found"; @@ -101,27 +101,27 @@ static void start_board_resources(void) { - rest_activate_resource(&res_toggle_green, "lt/g"); - rest_activate_resource(&res_toggle_red, "lt/r"); - rest_activate_resource(&res_leds, "lt"); + coap_activate_resource(&res_toggle_green, "lt/g"); + coap_activate_resource(&res_toggle_red, "lt/r"); + coap_activate_resource(&res_leds, "lt"); #if BOARD_SENSORTAG - rest_activate_resource(&res_bmp280_temp, "sen/bar/temp"); - rest_activate_resource(&res_bmp280_press, "sen/bar/pres"); - rest_activate_resource(&res_tmp007_amb, "sen/tmp/amb"); - rest_activate_resource(&res_tmp007_obj, "sen/tmp/obj"); - rest_activate_resource(&res_hdc1000_temp, "sen/hdc/t"); - rest_activate_resource(&res_hdc1000_hum, "sen/hdc/h"); - rest_activate_resource(&res_opt3001_light, "sen/opt/light"); - rest_activate_resource(&res_mpu_acc_x, "sen/mpu/acc/x"); - rest_activate_resource(&res_mpu_acc_y, "sen/mpu/acc/y"); - rest_activate_resource(&res_mpu_acc_z, "sen/mpu/acc/z"); - rest_activate_resource(&res_mpu_gyro_x, "sen/mpu/gyro/x"); - rest_activate_resource(&res_mpu_gyro_y, "sen/mpu/gyro/y"); - rest_activate_resource(&res_mpu_gyro_z, "sen/mpu/gyro/z"); + coap_activate_resource(&res_bmp280_temp, "sen/bar/temp"); + coap_activate_resource(&res_bmp280_press, "sen/bar/pres"); + coap_activate_resource(&res_tmp007_amb, "sen/tmp/amb"); + coap_activate_resource(&res_tmp007_obj, "sen/tmp/obj"); + coap_activate_resource(&res_hdc1000_temp, "sen/hdc/t"); + coap_activate_resource(&res_hdc1000_hum, "sen/hdc/h"); + coap_activate_resource(&res_opt3001_light, "sen/opt/light"); + coap_activate_resource(&res_mpu_acc_x, "sen/mpu/acc/x"); + coap_activate_resource(&res_mpu_acc_y, "sen/mpu/acc/y"); + coap_activate_resource(&res_mpu_acc_z, "sen/mpu/acc/z"); + coap_activate_resource(&res_mpu_gyro_x, "sen/mpu/gyro/x"); + coap_activate_resource(&res_mpu_gyro_y, "sen/mpu/gyro/y"); + coap_activate_resource(&res_mpu_gyro_z, "sen/mpu/gyro/z"); #elif BOARD_SMARTRF06EB - rest_activate_resource(&res_toggle_yellow, "lt/y"); - rest_activate_resource(&res_toggle_orange, "lt/o"); + coap_activate_resource(&res_toggle_yellow, "lt/y"); + coap_activate_resource(&res_toggle_orange, "lt/o"); #endif } /*---------------------------------------------------------------------------*/ @@ -134,25 +134,25 @@ PROCESS_THREAD(coap_server_process, ev, data) printf("CC26XX CoAP Server\n"); /* Initialize the REST engine. */ - rest_init_engine(); + coap_engine_init(); - rest_activate_resource(&res_batmon_temp, "sen/batmon/temp"); - rest_activate_resource(&res_batmon_volt, "sen/batmon/voltage"); + coap_activate_resource(&res_batmon_temp, "sen/batmon/temp"); + coap_activate_resource(&res_batmon_volt, "sen/batmon/voltage"); #if CC26XX_WEB_DEMO_ADC_DEMO - rest_activate_resource(&res_adc_dio23, "sen/adc/dio23"); + coap_activate_resource(&res_adc_dio23, "sen/adc/dio23"); #endif - rest_activate_resource(&res_device_hw, "dev/mdl/hw"); - rest_activate_resource(&res_device_sw, "dev/mdl/sw"); - rest_activate_resource(&res_device_uptime, "dev/uptime"); - rest_activate_resource(&res_device_cfg_reset, "dev/cfg_reset"); + coap_activate_resource(&res_device_hw, "dev/mdl/hw"); + coap_activate_resource(&res_device_sw, "dev/mdl/sw"); + coap_activate_resource(&res_device_uptime, "dev/uptime"); + coap_activate_resource(&res_device_cfg_reset, "dev/cfg_reset"); - rest_activate_resource(&res_parent_rssi, "net/parent/RSSI"); - rest_activate_resource(&res_parent_ip, "net/parent/IPv6"); + coap_activate_resource(&res_parent_rssi, "net/parent/RSSI"); + coap_activate_resource(&res_parent_ip, "net/parent/IPv6"); #if RF_BLE_ENABLED - rest_activate_resource(&res_ble_advd, "dev/ble_advd"); + coap_activate_resource(&res_ble_advd, "dev/ble_advd"); #endif start_board_resources(); diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/img/coap-resources.png b/examples/platform-specific/cc26xx/cc26xx-web-demo/img/coap-resources.png deleted file mode 100644 index c71c934fe8ab419f03c1ace336352b549e652eca..0000000000000000000000000000000000000000 Binary files a/examples/platform-specific/cc26xx/cc26xx-web-demo/img/coap-resources.png and /dev/null differ diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/mqtt-client.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/mqtt-client.c index 59ecee1ceeafb3b5da47f037db652207b8cc56a8..7562fb89a3298e938740c47401b853cd4ee7d8b2 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/mqtt-client.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/mqtt-client.c @@ -36,17 +36,14 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ +#include "net/routing/routing.h" #include "mqtt.h" -#include "rpl.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-icmp6.h" #include "sys/etimer.h" #include "sys/ctimer.h" #include "lib/sensors.h" -#include "button-sensor.h" +#include "dev/button-hal.h" #include "board-peripherals.h" #include "cc26xx-web-demo.h" #include "dev/leds.h" @@ -885,10 +882,14 @@ PROCESS_THREAD(mqtt_client_process, ev, data) PROCESS_YIELD(); - if(ev == sensors_event && data == CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER) { - if(state == MQTT_CLIENT_STATE_ERROR) { - connect_attempt = 1; - state = MQTT_CLIENT_STATE_REGISTERED; + if(ev == button_hal_release_event) { + button_hal_button_t *btn = (button_hal_button_t *)data; + + if(btn->unique_id == CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER) { + if(state == MQTT_CLIENT_STATE_ERROR) { + connect_attempt = 1; + state = MQTT_CLIENT_STATE_REGISTERED; + } } } @@ -904,7 +905,9 @@ PROCESS_THREAD(mqtt_client_process, ev, data) if((ev == PROCESS_EVENT_TIMER && data == &publish_periodic_timer) || ev == PROCESS_EVENT_POLL || ev == cc26xx_web_demo_publish_event || - (ev == sensors_event && data == CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER)) { + (ev == button_hal_release_event && + ((button_hal_button_t *)data)->unique_id == + CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER)) { state_machine(); } diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/net-uart.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/net-uart.c index f3dc146c95d681ffccc014948316a036d5448b5a..ca3bf8c82a0c5735252bbdf0883e8b59a337c269 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/net-uart.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/net-uart.c @@ -71,6 +71,7 @@ #include <stdint.h> #include <string.h> +#include <strings.h> #include <stdio.h> #include <stdlib.h> /*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/project-conf.h b/examples/platform-specific/cc26xx/cc26xx-web-demo/project-conf.h index 43095dfe98e649e5e10a4225f779dfb5205fc08e..40a1e8262efca3d88518714c1d265828b73e9694 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/project-conf.h +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/project-conf.h @@ -33,7 +33,7 @@ /*---------------------------------------------------------------------------*/ /* Change to match your configuration */ #define IEEE802154_CONF_PANID 0xABCD -#define RF_CORE_CONF_CHANNEL 25 +#define RF_CORE_CONF_CHANNEL 26 #define RF_BLE_CONF_ENABLED 1 /*---------------------------------------------------------------------------*/ @@ -42,7 +42,7 @@ /* Enable/Disable Components of this Demo */ #define CC26XX_WEB_DEMO_CONF_MQTT_CLIENT 1 -#define CC26XX_WEB_DEMO_CONF_6LBR_CLIENT 1 +#define CC26XX_WEB_DEMO_CONF_6LBR_CLIENT ROUTING_CONF_RPL_CLASSIC #define CC26XX_WEB_DEMO_CONF_COAP_SERVER 1 #define CC26XX_WEB_DEMO_CONF_NET_UART 1 @@ -60,9 +60,9 @@ * Shrink the size of the uIP buffer, routing table and ND cache. * Set the TCP MSS */ -#define UIP_CONF_BUFFER_SIZE 900 -#define NETSTCK_ROUTING_STATE_SIZE 5 -#define NBR_TABLE_CONF_MAX_NEIGHBORS 5 +#define UIP_CONF_BUFFER_SIZE 500 +#define NETSTACK_MAX_ROUTE_ENTRIES 5 +#define NBR_TABLE_CONF_MAX_NEIGHBORS 5 #define UIP_CONF_TCP_MSS 128 /*---------------------------------------------------------------------------*/ #endif /* PROJECT_CONF_H_ */ diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c index 2dccd1b75a79d5093e6f2b71f212a59e9137c309..a94a0b7a050506e60396f64ae073e9cbae7f3c9a 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c @@ -36,7 +36,7 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "rf-core/rf-ble.h" @@ -49,7 +49,8 @@ const char *forbidden_payload = "Name to advertise unspecified.\n" "Use name=<name> in the request"; /*---------------------------------------------------------------------------*/ static void -res_ble_post_put_handler(void *request, void *response, uint8_t *buffer, +res_ble_post_put_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { size_t len = 0; @@ -60,7 +61,7 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer, memset(name, 0, BLE_NAME_BUF_LEN); - len = REST.get_post_variable(request, "name", &text); + len = coap_get_post_variable(request, "name", &text); if(len > 0 && len < BLE_NAME_BUF_LEN) { memcpy(name, text, len); @@ -68,7 +69,7 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer, success = 1; } - len = REST.get_post_variable(request, "interval", &text); + len = coap_get_post_variable(request, "interval", &text); rv = atoi(text); @@ -77,15 +78,15 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer, success = 1; } - len = REST.get_post_variable(request, "mode", &text); + len = coap_get_post_variable(request, "mode", &text); if(len) { if(strncmp(text, "on", len) == 0) { if(rf_ble_beacond_start()) { success = 1; } else { - REST.set_response_status(response, REST.status.FORBIDDEN); - REST.set_response_payload(response, forbidden_payload, + coap_set_status_code(response, FORBIDDEN_4_03); + coap_set_payload(response, forbidden_payload, strlen(forbidden_payload)); return; } @@ -98,7 +99,7 @@ res_ble_post_put_handler(void *request, void *response, uint8_t *buffer, } if(!success) { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); } } /*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c index a52557ffed5f7d3fa0d10ea896d1a57c3ea2456f..46344d1efcfc76f53b407a3db56495eb4d2b73e2 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c @@ -37,7 +37,7 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "sys/clock.h" #include "coap-server.h" @@ -46,6 +46,7 @@ #include "ti-lib.h" #include <string.h> +#include <stdio.h> /*---------------------------------------------------------------------------*/ static uint16_t detect_chip(void) @@ -74,106 +75,110 @@ detect_chip(void) } /*---------------------------------------------------------------------------*/ static void -res_get_handler_hw(void *request, void *response, uint8_t *buffer, +res_get_handler_hw(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; uint16_t chip = detect_chip(); - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s on CC%u", BOARD_STRING, chip); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"HW Ver\":\"%s on CC%u\"}", BOARD_STRING, chip); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "<hw-ver val=\"%s on CC%u\"/>", BOARD_STRING, chip); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } /*---------------------------------------------------------------------------*/ static void -res_get_handler_sw(void *request, void *response, uint8_t *buffer, +res_get_handler_sw(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", CONTIKI_VERSION_STRING); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"SW Ver\":\"%s\"}", CONTIKI_VERSION_STRING); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "<sw-ver val=\"%s\"/>", CONTIKI_VERSION_STRING); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } /*---------------------------------------------------------------------------*/ static void -res_get_handler_uptime(void *request, void *response, uint8_t *buffer, +res_get_handler_uptime(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%lu", clock_seconds()); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"uptime\":%lu}", clock_seconds()); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "<uptime val=\"%lu\" unit=\"sec\"/>", clock_seconds()); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } /*---------------------------------------------------------------------------*/ static void -res_post_handler_cfg_reset(void *request, void *response, uint8_t *buffer, +res_post_handler_cfg_reset(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { cc26xx_web_demo_restore_defaults(); diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c index 85ce353b5e00f2b769b8cd9046f9db7e1ca704b4..6c396145c5b7a9e05c2b1805ea87ceefe625e645 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c @@ -40,13 +40,14 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/leds.h" #include <string.h> /*---------------------------------------------------------------------------*/ static void -res_post_put_handler(void *request, void *response, uint8_t *buffer, +res_post_put_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { size_t len = 0; @@ -55,7 +56,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, uint8_t led = 0; int success = 1; - if((len = REST.get_query_variable(request, "color", &color))) { + if((len = coap_get_query_variable(request, "color", &color))) { if(strncmp(color, "r", len) == 0) { led = LEDS_RED; } else if(strncmp(color, "g", len) == 0) { @@ -73,7 +74,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, success = 0; } - if(success && (len = REST.get_post_variable(request, "mode", &mode))) { + if(success && (len = coap_get_post_variable(request, "mode", &mode))) { if(strncmp(mode, "on", len) == 0) { leds_on(led); } else if(strncmp(mode, "off", len) == 0) { @@ -86,7 +87,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, } if(!success) { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); } } /*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c index 86346a999a1ff8f1e66ff5f2bd20863830351792..81575f345ed6ca7753c0054a0f137cd0ddd6dff1 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c @@ -37,82 +37,86 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" +#include "net/ipv6/uip-ds6.h" #include "coap-server.h" #include "cc26xx-web-demo.h" #include "ti-lib.h" #include <string.h> +#include <stdio.h> /*---------------------------------------------------------------------------*/ extern int def_rt_rssi; /*---------------------------------------------------------------------------*/ static void -res_get_handler_parent_rssi(void *request, void *response, uint8_t *buffer, +res_get_handler_parent_rssi(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", def_rt_rssi); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%d", def_rt_rssi); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"Parent RSSI\":\"%d\"}", + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{\"Parent RSSI\":\"%d\"}", def_rt_rssi); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "<parent-rssi val=\"%d\"/>", def_rt_rssi); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } /*---------------------------------------------------------------------------*/ static void -res_get_handler_pref_parent(void *request, void *response, uint8_t *buffer, +res_get_handler_pref_parent(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; char def_rt_str[64]; - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); memset(def_rt_str, 0, sizeof(def_rt_str)); cc26xx_web_demo_ipaddr_sprintf(def_rt_str, sizeof(def_rt_str), uip_ds6_defrt_choose()); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", def_rt_str); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "%s", def_rt_str); - REST.set_response_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"Parent\":\"%s\"}", + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{\"Parent\":\"%s\"}", def_rt_str); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "<parent=\"%s\"/>", def_rt_str); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c index b5fe9adb9c4d38315e1daded577811631fd0eec6..9ccc79e977eaa082d3eabd82baa9b8ea607934e9 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c @@ -37,7 +37,7 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #include "cc26xx-web-demo.h" #include "coap-server.h" @@ -51,7 +51,8 @@ * called by all handlers and populates the CoAP response */ static void -res_get_handler_all(int sens_type, void *request, void *response, +res_get_handler_all(int sens_type, coap_message_t *request, + coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; @@ -60,43 +61,44 @@ res_get_handler_all(int sens_type, void *request, void *response, reading = cc26xx_web_demo_sensor_lookup(sens_type); if(reading == NULL) { - REST.set_response_status(response, REST.status.NOT_FOUND); - REST.set_response_payload(response, coap_server_not_found_msg, + coap_set_status_code(response, NOT_FOUND_4_04); + coap_set_payload(response, coap_server_not_found_msg, strlen(coap_server_not_found_msg)); return; } - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", reading->converted); - REST.set_response_payload(response, (uint8_t *)buffer, + coap_set_payload(response, (uint8_t *)buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + } else if(accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{\"%s\":%s}", reading->descr, reading->converted); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.APPLICATION_XML) { - REST.set_header_content_type(response, REST.type.APPLICATION_XML); + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "<%s val=\"%s\" unit=\"%s\"/>", reading->xml_element, reading->converted, reading->units); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, coap_server_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, coap_server_supported_msg, strlen(coap_server_supported_msg)); } } /*---------------------------------------------------------------------------*/ /* BatMon resources and handler: Temperature, Voltage */ static void -res_get_handler_batmon_temp(void *request, void *response, uint8_t *buffer, +res_get_handler_batmon_temp(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BATMON_TEMP, request, response, @@ -104,7 +106,8 @@ res_get_handler_batmon_temp(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_batmon_volt(void *request, void *response, uint8_t *buffer, +res_get_handler_batmon_volt(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BATMON_VOLT, request, response, @@ -120,7 +123,8 @@ RESOURCE(res_batmon_volt, "title=\"Battery Voltage\";rt=\"mV\"", #if CC26XX_WEB_DEMO_ADC_DEMO /*---------------------------------------------------------------------------*/ static void -res_get_handler_adc_dio23(void *request, void *response, uint8_t *buffer, +res_get_handler_adc_dio23(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_ADC_DIO23, request, response, @@ -136,7 +140,8 @@ RESOURCE(res_adc_dio23, "title=\"ADC DIO23\";rt=\"mV\"", /*---------------------------------------------------------------------------*/ /* MPU resources and handler: Accelerometer and Gyro */ static void -res_get_handler_mpu_acc_x(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_acc_x(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_X, request, response, @@ -144,7 +149,8 @@ res_get_handler_mpu_acc_x(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_acc_y(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_acc_y(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Y, request, response, @@ -152,7 +158,8 @@ res_get_handler_mpu_acc_y(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_acc_z(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_acc_z(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Z, request, response, @@ -160,7 +167,8 @@ res_get_handler_mpu_acc_z(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_gyro_x(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_gyro_x(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_X, request, response, @@ -168,7 +176,8 @@ res_get_handler_mpu_gyro_x(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_gyro_y(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_gyro_y(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Y, request, response, @@ -176,7 +185,8 @@ res_get_handler_mpu_gyro_y(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_mpu_gyro_z(void *request, void *response, uint8_t *buffer, +res_get_handler_mpu_gyro_z(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Z, request, response, @@ -199,7 +209,8 @@ RESOURCE(res_mpu_gyro_z, "title=\"Gyro Z\";rt=\"deg/sec\"", /*---------------------------------------------------------------------------*/ /* TMP sensor resources and handlers: Object, Ambient */ static void -res_get_handler_obj_temp(void *request, void *response, uint8_t *buffer, +res_get_handler_obj_temp(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_TMP_OBJECT, request, response, @@ -207,7 +218,8 @@ res_get_handler_obj_temp(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_amb_temp(void *request, void *response, uint8_t *buffer, +res_get_handler_amb_temp(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_TMP_AMBIENT, request, response, @@ -222,7 +234,8 @@ RESOURCE(res_tmp007_amb, "title=\"Temperature (Ambient)\";rt=\"C\"", /*---------------------------------------------------------------------------*/ /* BMP sensor resources: Temperature, Pressure */ static void -res_get_handler_bmp_temp(void *request, void *response, uint8_t *buffer, +res_get_handler_bmp_temp(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BMP_TEMP, request, response, @@ -230,7 +243,8 @@ res_get_handler_bmp_temp(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_bmp_press(void *request, void *response, uint8_t *buffer, +res_get_handler_bmp_press(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_BMP_PRES, request, response, @@ -246,7 +260,8 @@ RESOURCE(res_bmp280_press, /*---------------------------------------------------------------------------*/ /* HDC1000 sensor resources and handler: Temperature, Pressure */ static void -res_get_handler_hdc_temp(void *request, void *response, uint8_t *buffer, +res_get_handler_hdc_temp(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_HDC_TEMP, request, response, @@ -254,7 +269,8 @@ res_get_handler_hdc_temp(void *request, void *response, uint8_t *buffer, } /*---------------------------------------------------------------------------*/ static void -res_get_handler_hdc_humidity(void *request, void *response, uint8_t *buffer, +res_get_handler_hdc_humidity(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_HDC_HUMIDITY, request, response, @@ -269,7 +285,8 @@ RESOURCE(res_hdc1000_hum, "title=\"Humidity\";rt=\"%RH\"", /*---------------------------------------------------------------------------*/ /* Illuminance resources and handler */ static void -res_get_handler_opt(void *request, void *response, uint8_t *buffer, +res_get_handler_opt(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_OPT_LIGHT, request, response, diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c index 2fb424a03db8227165209d11199ddcadbfc0c77e..1c708b53979d3f5f89ae513efb8520a674ae24a7 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c @@ -42,20 +42,22 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "dev/leds.h" #include <string.h> /*---------------------------------------------------------------------------*/ static void -res_post_handler_red(void *request, void *response, uint8_t *buffer, +res_post_handler_red(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_RED); } /*---------------------------------------------------------------------------*/ static void -res_post_handler_green(void *request, void *response, uint8_t *buffer, +res_post_handler_green(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_GREEN); @@ -81,14 +83,16 @@ RESOURCE(res_toggle_green, #if BOARD_SMARTRF06EB /*---------------------------------------------------------------------------*/ static void -res_post_handler_yellow(void *request, void *response, uint8_t *buffer, +res_post_handler_yellow(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_YELLOW); } /*---------------------------------------------------------------------------*/ static void -res_post_handler_orange(void *request, void *response, uint8_t *buffer, +res_post_handler_orange(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_ORANGE); diff --git a/examples/platform-specific/cc26xx/project-conf.h b/examples/platform-specific/cc26xx/project-conf.h index fc2d23ab1b1bba0fe60c58af63973fddd39b8267..8231dd4eafe5e2f614465a1f5e4bc4f5f3baae4a 100644 --- a/examples/platform-specific/cc26xx/project-conf.h +++ b/examples/platform-specific/cc26xx/project-conf.h @@ -31,9 +31,6 @@ #ifndef PROJECT_CONF_H_ #define PROJECT_CONF_H_ /*---------------------------------------------------------------------------*/ -/* Disable button shutdown functionality */ -#define BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN 0 -/*---------------------------------------------------------------------------*/ /* Enable the ROM bootloader */ #define ROM_BOOTLOADER_ENABLE 1 /*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/cc26xx/very-sleepy-demo/Makefile b/examples/platform-specific/cc26xx/very-sleepy-demo/Makefile index 21f6acc1d4c6b999db956a74ed48f59043d71276..46da822d30de30865dc3c9aeade785630b8c713d 100644 --- a/examples/platform-specific/cc26xx/very-sleepy-demo/Makefile +++ b/examples/platform-specific/cc26xx/very-sleepy-demo/Makefile @@ -1,5 +1,7 @@ CONTIKI_PROJECT = very-sleepy-demo +PLATFORMS_ONLY = srf06-cc26xx + all: $(CONTIKI_PROJECT) MODULES += os/net/app-layer/coap diff --git a/examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c b/examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c index e56ee93e6a25c0b37aaa67dade5c0c30ddc0f8fa..cac8033b75d8fe281e812d03ab9e2381fdccc5e6 100644 --- a/examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c +++ b/examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c @@ -34,17 +34,14 @@ #include "sys/process.h" #include "dev/leds.h" #include "dev/watchdog.h" -#include "button-sensor.h" +#include "dev/button-hal.h" #include "batmon-sensor.h" #include "board-peripherals.h" #include "net/netstack.h" #include "net/ipv6/uip-ds6-nbr.h" #include "net/ipv6/uip-ds6-route.h" -#include "rpl.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ -#include "rest-engine.h" +#include "net/routing/routing.h" +#include "coap-engine.h" #include "coap.h" #include "ti-lib.h" @@ -66,6 +63,8 @@ #define VERY_SLEEPY_MODE_OFF 0 #define VERY_SLEEPY_MODE_ON 1 /*---------------------------------------------------------------------------*/ +#define BUTTON_TRIGGER BOARD_BUTTON_HAL_INDEX_KEY_LEFT +/*---------------------------------------------------------------------------*/ #define MAC_CAN_BE_TURNED_OFF 0 #define MAC_MUST_STAY_ON 1 @@ -104,38 +103,38 @@ PROCESS(very_sleepy_demo_process, "CC13xx/CC26xx very sleepy process"); AUTOSTART_PROCESSES(&very_sleepy_demo_process); /*---------------------------------------------------------------------------*/ static void -readings_get_handler(void *request, void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +readings_get_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; int temp; int voltage; if(request != NULL) { - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); } temp = batmon_sensor.value(BATMON_SENSOR_TYPE_TEMP); voltage = batmon_sensor.value(BATMON_SENSOR_TYPE_VOLT); - if(accept == -1 || accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + if(accept == -1 || accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{\"temp\":{\"v\":%d,\"u\":\"C\"}," "\"voltage\":{\"v\":%d,\"u\":\"mV\"}}", temp, (voltage * 125) >> 5); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "Temp=%dC, Voltage=%dmV", + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "Temp=%dC, Voltage=%dmV", temp, (voltage * 125) >> 5); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, not_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, not_supported_msg, strlen(not_supported_msg)); } } @@ -144,39 +143,39 @@ RESOURCE(readings_resource, "title=\"Sensor Readings\";obs", readings_get_handler, NULL, NULL, NULL); /*---------------------------------------------------------------------------*/ static void -conf_get_handler(void *request, void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +conf_get_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; if(request != NULL) { - REST.get_header_accept(request, &accept); + coap_get_header_accept(request, &accept); } - if(accept == -1 || accept == REST.type.APPLICATION_JSON) { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + if(accept == -1 || accept == APPLICATION_JSON) { + coap_set_header_content_format(response, APPLICATION_JSON); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "{\"config\":{\"mode\":%u,\"duration\":%lu,\"interval\":%lu}}", config.mode, config.duration, config.interval); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); - } else if(accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + coap_set_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "Mode=%u, Duration=%lusecs, Interval=%lusecs", config.mode, config.duration, config.interval); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); } else { - REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); - REST.set_response_payload(response, not_supported_msg, + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + coap_set_payload(response, not_supported_msg, strlen(not_supported_msg)); } } /*---------------------------------------------------------------------------*/ static void -conf_post_handler(void *request, void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +conf_post_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *ptr = NULL; char tmp_buf[16]; @@ -186,7 +185,7 @@ conf_post_handler(void *request, void *response, uint8_t *buffer, uint8_t post_status = POST_STATUS_NONE; int rv; - rv = REST.get_post_variable(request, "mode", &ptr); + rv = coap_get_post_variable(request, "mode", &ptr); if(rv && rv < 16) { memset(tmp_buf, 0, sizeof(tmp_buf)); memcpy(tmp_buf, ptr, rv); @@ -203,7 +202,7 @@ conf_post_handler(void *request, void *response, uint8_t *buffer, } } - rv = REST.get_post_variable(request, "duration", &ptr); + rv = coap_get_post_variable(request, "duration", &ptr); if(rv && rv < 16) { memset(tmp_buf, 0, sizeof(tmp_buf)); memcpy(tmp_buf, ptr, rv); @@ -217,7 +216,7 @@ conf_post_handler(void *request, void *response, uint8_t *buffer, } } - rv = REST.get_post_variable(request, "interval", &ptr); + rv = coap_get_post_variable(request, "interval", &ptr); if(rv && rv < 16) { memset(tmp_buf, 0, sizeof(tmp_buf)); memcpy(tmp_buf, ptr, rv); @@ -232,13 +231,13 @@ conf_post_handler(void *request, void *response, uint8_t *buffer, if((post_status & POST_STATUS_BAD) == POST_STATUS_BAD || post_status == POST_STATUS_NONE) { - REST.set_response_status(response, REST.status.BAD_REQUEST); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, + coap_set_status_code(response, BAD_REQUEST_4_00); + snprintf((char *)buffer, COAP_MAX_CHUNK_SIZE, "mode=0|1&duration=[%u,%u]&interval=[%u,%u]", NORMAL_OP_DURATION_MIN, NORMAL_OP_DURATION_MAX, PERIODIC_INTERVAL_MIN, PERIODIC_INTERVAL_MAX); - REST.set_response_payload(response, buffer, strlen((char *)buffer)); + coap_set_payload(response, buffer, strlen((char *)buffer)); return; } @@ -345,11 +344,11 @@ PROCESS_THREAD(very_sleepy_demo_process, ev, data) event_new_config = process_alloc_event(); - rest_init_engine(); + coap_engine_init(); readings_resource.flags += IS_OBSERVABLE; - rest_activate_resource(&readings_resource, "sen/readings"); - rest_activate_resource(&very_sleepy_conf, "very_sleepy_config"); + coap_activate_resource(&readings_resource, "sen/readings"); + coap_activate_resource(&very_sleepy_conf, "very_sleepy_config"); printf("Very Sleepy Demo Process\n"); @@ -361,7 +360,8 @@ PROCESS_THREAD(very_sleepy_demo_process, ev, data) PROCESS_YIELD(); - if(ev == sensors_event && data == &button_left_sensor) { + if(ev == button_hal_release_event && + ((button_hal_button_t *)data)->unique_id == BUTTON_TRIGGER) { switch_to_normal(); } @@ -371,7 +371,8 @@ PROCESS_THREAD(very_sleepy_demo_process, ev, data) } if((ev == PROCESS_EVENT_TIMER && data == &et_periodic) || - (ev == sensors_event && data == &button_left_sensor) || + (ev == button_hal_release_event && + ((button_hal_button_t *)data)->unique_id == BUTTON_TRIGGER) || (ev == event_new_config)) { /* @@ -390,7 +391,7 @@ PROCESS_THREAD(very_sleepy_demo_process, ev, data) * send notifications to observers as required. */ if(state == STATE_NOTIFY_OBSERVERS) { - REST.notify_subscribers(&readings_resource); + coap_notify_observers(&readings_resource); state = STATE_NORMAL; } diff --git a/examples/platform-specific/jn516x/dr1175-sensors/Makefile b/examples/platform-specific/jn516x/dr1175-sensors/Makefile index 90be80149a73377ac3d14b068bf99655a74011e8..23b1c50d774106164f7abe92351a41b9589aabd5 100644 --- a/examples/platform-specific/jn516x/dr1175-sensors/Makefile +++ b/examples/platform-specific/jn516x/dr1175-sensors/Makefile @@ -1,6 +1,8 @@ CONTIKI=../../../.. CONTIKI_PROJECT = node +PLATFORMS_ONLY = jn516x + TARGET ?= jn516x JN516x_WITH_DR1175 = 1 diff --git a/examples/platform-specific/jn516x/rpl/coap-dongle-node/Makefile b/examples/platform-specific/jn516x/rpl/coap-dongle-node/Makefile index 1b13ef3e07fba8b5f06870775319b59a69153a63..d0437d869f0282f443cc7159717cf50096a44f54 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dongle-node/Makefile +++ b/examples/platform-specific/jn516x/rpl/coap-dongle-node/Makefile @@ -1,6 +1,8 @@ CONTIKI_PROJECT = dongle-node all: $(CONTIKI_PROJECT) +PLATFORMS_ONLY = jn516x + TARGET ?= jn516x JN516x_WITH_DONGLE = 1 @@ -8,8 +10,7 @@ CONTIKI=../../../../.. MAKE_MAC = MAKE_MAC_TSCH MODULES += os/lib/json -PROJECTDIRS += .. ../tools -PROJECT_SOURCEFILES += rpl-tools.c +MODULES_REL += .. MODULES += os/net/app-layer/coap diff --git a/examples/platform-specific/jn516x/rpl/coap-dongle-node/dongle-node.c b/examples/platform-specific/jn516x/rpl/coap-dongle-node/dongle-node.c index 1e3ab08422f378698edc7ee1691ab1f1137d440a..2fb2d7761026902a2f2a99f7a2c65d2d09f8b3e1 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dongle-node/dongle-node.c +++ b/examples/platform-specific/jn516x/rpl/coap-dongle-node/dongle-node.c @@ -34,16 +34,16 @@ #include "contiki.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" -#include "tools/rpl-tools.h" -#include "rest-engine.h" +#include "net/routing/routing.h" +#include "coap-engine.h" #include "sys/ctimer.h" #include <stdio.h> #include "dev/leds.h" static void ct_callback(void *ptr); -static void put_post_led_toggle_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_toggle_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static char content[REST_MAX_CHUNK_SIZE]; +static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; static struct ctimer ct; @@ -77,7 +77,7 @@ RESOURCE(resource_led_toggle, put_post_led_toggle_handler, NULL); static void -put_post_led_toggle_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_toggle_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { static int led_state = 0; unsigned int accept = -1; @@ -110,10 +110,10 @@ put_post_led_toggle_handler(void *request, void *response, uint8_t *buffer, uint break; } /* Return message */ - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /*---------------------------------------------------------------------------*/ @@ -130,15 +130,13 @@ PROCESS_THREAD(start_app, ev, data) /* Start net stack */ if(is_coordinator) { - uip_ipaddr_t prefix; - uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); - rpl_tools_init(&prefix); - } else { - rpl_tools_init(NULL); - } printf("Starting RPL node\n"); + NETSTACK_ROUTING.root_start(); + } + NETSTACK_MAC.on(); + printf("Starting RPL node\n"); - rest_init_engine(); - rest_activate_resource(&resource_led_toggle, "Dongle/LED-toggle"); + coap_engine_init(); + coap_activate_resource(&resource_led_toggle, "Dongle/LED-toggle"); PROCESS_END(); } diff --git a/examples/platform-specific/jn516x/rpl/coap-dongle-node/project-conf.h b/examples/platform-specific/jn516x/rpl/coap-dongle-node/project-conf.h index a46f32f1cbcfa265f1993120524fcd31ede09617..bb7d4d78501290d018d09f0e2a6b0f19f6be18d1 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dongle-node/project-conf.h +++ b/examples/platform-specific/jn516x/rpl/coap-dongle-node/project-conf.h @@ -31,11 +31,11 @@ * \author Simon Duquennoy <simonduq@sics.se> */ -#ifndef __PROJECT_CONF_H__ -#define __PROJECT_CONF_H__ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ #define UIP_CONF_TCP 0 #include "../common-conf.h" -#endif /* __PROJECT_CONF_H__ */ +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/platform-specific/jn516x/rpl/coap-dr1175-node/Makefile b/examples/platform-specific/jn516x/rpl/coap-dr1175-node/Makefile index 9a393ff140480832eab9e23ddcbba3fa39bd2b3c..3670d12c45ac101aff289d8c756e79d4c3030614 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dr1175-node/Makefile +++ b/examples/platform-specific/jn516x/rpl/coap-dr1175-node/Makefile @@ -1,6 +1,8 @@ CONTIKI_PROJECT = dr1175-node all: $(CONTIKI_PROJECT) +PLATFORMS_ONLY = jn516x + TARGET ?= jn516x JN516x_WITH_DR1175 = 1 @@ -8,8 +10,7 @@ CONTIKI=../../../../.. MAKE_MAC = MAKE_MAC_TSCH MODULES += os/lib/json -PROJECTDIRS += .. ../tools -PROJECT_SOURCEFILES += rpl-tools.c +MODULES_REL += .. MODULES += os/net/app-layer/coap diff --git a/examples/platform-specific/jn516x/rpl/coap-dr1175-node/dr1175-node.c b/examples/platform-specific/jn516x/rpl/coap-dr1175-node/dr1175-node.c index 2cd40c2834914a0dfdecfbe8adb2ee2435656575..443cf4fbe40f3b7d23f6a914ac43c4db0cffe400 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dr1175-node/dr1175-node.c +++ b/examples/platform-specific/jn516x/rpl/coap-dr1175-node/dr1175-node.c @@ -35,8 +35,8 @@ #include "contiki.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" -#include "tools/rpl-tools.h" -#include "rest-engine.h" +#include "net/routing/routing.h" +#include "coap-engine.h" #include "light-sensor.h" #include "ht-sensor.h" #include "dev/leds.h" @@ -46,19 +46,19 @@ #include <stdlib.h> static void event_sensors_dr1175_handler(void); -static void get_sensors_dr1175_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_light_sensor_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_light_sensor_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_temperature_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_temperature_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_humidity_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_humidity_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_white_led_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_rgb_led_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d3_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d6_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_sensors_dr1175_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_light_sensor_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_light_sensor_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_temperature_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_temperature_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_humidity_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_humidity_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_white_led_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_rgb_led_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d3_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d6_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static char content[REST_MAX_CHUNK_SIZE]; +static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; #define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) { content_len += snprintf(content + content_len, sizeof(content) - content_len, __VA_ARGS__); } } @@ -90,26 +90,26 @@ EVENT_RESOURCE(resource_sensors_dr1175, /* name */ NULL, /* DELETE handler */ event_sensors_dr1175_handler); /* event handler */ static void -get_sensors_dr1175_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_sensors_dr1175_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.APPLICATION_JSON) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == APPLICATION_JSON) { content_len = 0; CONTENT_PRINTF("{\"DR1175\":["); CONTENT_PRINTF("{\"Humidity\":\"%d\"},", ht_sensor.value(HT_SENSOR_HUM)); CONTENT_PRINTF("{\"Light\":\"%d\"},", light_sensor.value(0)); CONTENT_PRINTF("{\"Temp\":\"%d\"}", ht_sensor.value(HT_SENSOR_TEMP)); CONTENT_PRINTF("]}"); - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)content, content_len); } } static void event_sensors_dr1175_handler() { /* Registered observers are notified and will trigger the GET handler to create the response. */ - REST.notify_subscribers(&resource_sensors_dr1175); + coap_notify_observers(&resource_sensors_dr1175); } /*****************************************************/ /* Resource and handler to obtain light sensor value */ @@ -121,15 +121,15 @@ RESOURCE(resource_light_sensor_value, NULL, NULL); static void -get_light_sensor_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_light_sensor_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("%d", light_sensor.value(0)); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /***************************************************/ @@ -142,15 +142,15 @@ RESOURCE(resource_light_sensor_unit, NULL, NULL); static void -get_light_sensor_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_light_sensor_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("Lux"); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /***********************************************************/ @@ -163,15 +163,15 @@ RESOURCE(resource_temperature_value, NULL, NULL); static void -get_temperature_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_temperature_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("%d", ht_sensor.value(HT_SENSOR_TEMP)); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /*********************************************************/ @@ -184,15 +184,15 @@ RESOURCE(resource_temperature_unit, NULL, NULL); static void -get_temperature_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_temperature_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("degrees C"); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /********************************************************/ @@ -205,15 +205,15 @@ RESOURCE(resource_humidity_value, NULL, NULL); static void -get_humidity_value_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_humidity_value_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("%d", ht_sensor.value(HT_SENSOR_HUM)); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /******************************************************/ @@ -226,15 +226,15 @@ RESOURCE(resource_humidity_unit, NULL, NULL); static void -get_humidity_unit_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_humidity_unit_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("relative %%"); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /***************************************************/ @@ -247,15 +247,15 @@ RESOURCE(resource_white_led, put_post_white_led_handler, NULL); static void -put_post_white_led_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_white_led_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content = NULL; int level; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); level = atoi((const char *)request_content); CLIP(level, 255) leds_set_level(level, LEDS_WHITE); @@ -271,7 +271,7 @@ RESOURCE(resource_rgb_led, put_post_rgb_led_handler, NULL); static void -put_post_rgb_led_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_rgb_led_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content = NULL; char *pch; @@ -279,9 +279,9 @@ put_post_rgb_led_handler(void *request, void *response, uint8_t *buffer, uint16_ int index = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); pch = strtok((char *)request_content, " "); while((pch != NULL) && (index != sizeof(RGB) / sizeof(int))) { /* Convert token to int */ @@ -306,13 +306,13 @@ RESOURCE(resource_led_d3_1174, put_post_led_d3_1174_handler, NULL); static void -put_post_led_d3_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d3_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_GP0); } } @@ -326,13 +326,13 @@ RESOURCE(resource_led_d6_1174, put_post_led_d6_1174_handler, NULL); static void -put_post_led_d6_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d6_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_GP1); } } @@ -350,25 +350,23 @@ PROCESS_THREAD(start_app, ev, data) /* Start net stack */ if(is_coordinator) { - uip_ipaddr_t prefix; - uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); - rpl_tools_init(&prefix); - } else { - rpl_tools_init(NULL); - } printf("Starting RPL node\n"); + NETSTACK_ROUTING.root_start(); + } + NETSTACK_MAC.on(); + printf("Starting RPL node\n"); - rest_init_engine(); - rest_activate_resource(&resource_light_sensor_value, "DR1175/LightSensor/Value"); - rest_activate_resource(&resource_light_sensor_unit, "DR1175/LightSensor/Unit"); - rest_activate_resource(&resource_temperature_unit, "DR1175/Temperature/Unit"); - rest_activate_resource(&resource_temperature_value, "DR1175/Temperature/Value"); - rest_activate_resource(&resource_humidity_unit, "DR1175/Humidity/Unit"); - rest_activate_resource(&resource_humidity_value, "DR1175/Humidity/Value"); - rest_activate_resource(&resource_white_led, "DR1175/WhiteLED"); - rest_activate_resource(&resource_rgb_led, "DR1175/ColorLED/RGBValue"); - rest_activate_resource(&resource_led_d3_1174, "DR1175/LED/D3On1174"); - rest_activate_resource(&resource_led_d6_1174, "DR1175/LED/D6On1174"); - rest_activate_resource(&resource_sensors_dr1175, "DR1175/AllSensors"); + coap_engine_init(); + coap_activate_resource(&resource_light_sensor_value, "DR1175/LightSensor/Value"); + coap_activate_resource(&resource_light_sensor_unit, "DR1175/LightSensor/Unit"); + coap_activate_resource(&resource_temperature_unit, "DR1175/Temperature/Unit"); + coap_activate_resource(&resource_temperature_value, "DR1175/Temperature/Value"); + coap_activate_resource(&resource_humidity_unit, "DR1175/Humidity/Unit"); + coap_activate_resource(&resource_humidity_value, "DR1175/Humidity/Value"); + coap_activate_resource(&resource_white_led, "DR1175/WhiteLED"); + coap_activate_resource(&resource_rgb_led, "DR1175/ColorLED/RGBValue"); + coap_activate_resource(&resource_led_d3_1174, "DR1175/LED/D3On1174"); + coap_activate_resource(&resource_led_d6_1174, "DR1175/LED/D6On1174"); + coap_activate_resource(&resource_sensors_dr1175, "DR1175/AllSensors"); /* Level of LEDS=0, so no light after start-up */ leds_on(LEDS_WHITE | LEDS_RED | LEDS_GREEN | LEDS_BLUE); diff --git a/examples/platform-specific/jn516x/rpl/coap-dr1175-node/project-conf.h b/examples/platform-specific/jn516x/rpl/coap-dr1175-node/project-conf.h index a46f32f1cbcfa265f1993120524fcd31ede09617..bb7d4d78501290d018d09f0e2a6b0f19f6be18d1 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dr1175-node/project-conf.h +++ b/examples/platform-specific/jn516x/rpl/coap-dr1175-node/project-conf.h @@ -31,11 +31,11 @@ * \author Simon Duquennoy <simonduq@sics.se> */ -#ifndef __PROJECT_CONF_H__ -#define __PROJECT_CONF_H__ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ #define UIP_CONF_TCP 0 #include "../common-conf.h" -#endif /* __PROJECT_CONF_H__ */ +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/platform-specific/jn516x/rpl/coap-dr1199-node/Makefile b/examples/platform-specific/jn516x/rpl/coap-dr1199-node/Makefile index 32231f636aba848fa91e7759d6ccf5facd5194c3..b2286e272b774ff12ae93c954d014346e0955eb6 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dr1199-node/Makefile +++ b/examples/platform-specific/jn516x/rpl/coap-dr1199-node/Makefile @@ -1,6 +1,8 @@ CONTIKI_PROJECT = dr1199-node all: $(CONTIKI_PROJECT) +PLATFORMS_ONLY = jn516x + TARGET ?= jn516x JN516x_WITH_DR1199 = 1 @@ -8,8 +10,7 @@ CONTIKI=../../../../.. MAKE_MAC = MAKE_MAC_TSCH MODULES += os/lib/json -PROJECTDIRS += .. ../tools -PROJECT_SOURCEFILES += rpl-tools.c +MODULES_REL += .. MODULES += os/net/app-layer/coap diff --git a/examples/platform-specific/jn516x/rpl/coap-dr1199-node/dr1199-node.c b/examples/platform-specific/jn516x/rpl/coap-dr1199-node/dr1199-node.c index 0309538ec5a4a1cd31d261a114abb84544916a0b..d341170add45521c9e418132b8b388ea20d4052e 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dr1199-node/dr1199-node.c +++ b/examples/platform-specific/jn516x/rpl/coap-dr1199-node/dr1199-node.c @@ -34,31 +34,31 @@ #include "contiki.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" -#include "tools/rpl-tools.h" -#include "rest-engine.h" +#include "net/routing/routing.h" +#include "coap-engine.h" #include "dev/leds.h" #include "button-sensor.h" #include "pot-sensor.h" #include <stdio.h> #include <stdlib.h> -static char content[REST_MAX_CHUNK_SIZE]; +static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; static void event_sensors_dr1199_handler(); -static void get_sensors_dr1199_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_sw1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_sw2_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_sw3_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_sw4_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_switch_dio8_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_pot_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d2_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d3_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d3_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_d6_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void put_post_led_all_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_sensors_dr1199_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_sw1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_sw2_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_sw3_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_sw4_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_switch_dio8_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_pot_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d2_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d3_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d3_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_d6_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_led_all_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); #define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) { content_len += snprintf(content + content_len, sizeof(content) - content_len, __VA_ARGS__); } } @@ -93,25 +93,25 @@ EVENT_RESOURCE(resource_sensors_dr1199, /* name */ NULL, /* DELETE handler */ event_sensors_dr1199_handler); /* event handler */ static void -get_sensors_dr1199_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_sensors_dr1199_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.APPLICATION_JSON) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == APPLICATION_JSON) { content_len = 0; CONTENT_PRINTF("{\"DR1199\":["); CONTENT_PRINTF("{\"Switch\":\"0x%X\"},", button_sensor.value(0)); CONTENT_PRINTF("{\"Pot\":\"%d\"}", pot_sensor.value(0)); CONTENT_PRINTF("]}"); - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, APPLICATION_JSON); + coap_set_payload(response, (uint8_t *)content, content_len); } } static void event_sensors_dr1199_handler() { /* Registered observers are notified and will trigger the GET handler to create the response. */ - REST.notify_subscribers(&resource_sensors_dr1199); + coap_notify_observers(&resource_sensors_dr1199); } /***********************************************/ /* Resource and handler to obtain switch value */ @@ -123,15 +123,15 @@ RESOURCE(resource_switch_sw1, NULL, NULL); static void -get_switch_sw1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_sw1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { PARSE_SWITCH(1) - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } RESOURCE(resource_switch_sw2, @@ -141,15 +141,15 @@ RESOURCE(resource_switch_sw2, NULL, NULL); static void -get_switch_sw2_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_sw2_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { PARSE_SWITCH(2) - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } RESOURCE(resource_switch_sw3, @@ -159,15 +159,15 @@ RESOURCE(resource_switch_sw3, NULL, NULL); static void -get_switch_sw3_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_sw3_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { PARSE_SWITCH(3) - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } RESOURCE(resource_switch_sw4, @@ -177,15 +177,15 @@ RESOURCE(resource_switch_sw4, NULL, NULL); static void -get_switch_sw4_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_sw4_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { PARSE_SWITCH(4) - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } RESOURCE(resource_switch_dio8, @@ -195,15 +195,15 @@ RESOURCE(resource_switch_dio8, NULL, NULL); static void -get_switch_dio8_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_switch_dio8_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { PARSE_SWITCH(0) - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /*******************************************************/ @@ -216,15 +216,15 @@ RESOURCE(resource_pot, NULL, NULL); static void -get_pot_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_pot_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { content_len = 0; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { CONTENT_PRINTF("%d", pot_sensor.value(0)); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /************************************/ @@ -237,13 +237,13 @@ RESOURCE(resource_led_d1, put_post_led_d1_handler, NULL); static void -put_post_led_d1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_GREEN) } } @@ -254,13 +254,13 @@ RESOURCE(resource_led_d2, put_post_led_d2_handler, NULL); static void -put_post_led_d2_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d2_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_BLUE) } } @@ -271,13 +271,13 @@ RESOURCE(resource_led_d3, put_post_led_d3_handler, NULL); static void -put_post_led_d3_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d3_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_RED) } } @@ -288,13 +288,13 @@ RESOURCE(resource_led_d3_1174, put_post_led_d3_1174_handler, NULL); static void -put_post_led_d3_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d3_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_GP0); } } @@ -305,13 +305,13 @@ RESOURCE(resource_led_d6_1174, put_post_led_d6_1174_handler, NULL); static void -put_post_led_d6_1174_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_d6_1174_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); SET_LED(LEDS_GP1); } } @@ -322,13 +322,13 @@ RESOURCE(resource_led_all, put_post_led_all_handler, NULL); static void -put_post_led_all_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_led_all_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); if(atoi((const char *)request_content) != 0) { leds_on(LEDS_ALL); } else { @@ -351,27 +351,25 @@ PROCESS_THREAD(start_app, ev, data) /* Start net stack */ if(is_coordinator) { - uip_ipaddr_t prefix; - uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); - rpl_tools_init(&prefix); - } else { - rpl_tools_init(NULL); - } printf("Starting RPL node\n"); + NETSTACK_ROUTING.root_start(); + } + NETSTACK_MAC.on(); + printf("Starting RPL node\n"); - rest_init_engine(); - rest_activate_resource(&resource_switch_sw1, "DR1199/Switch/SW1"); - rest_activate_resource(&resource_switch_sw2, "DR1199/Switch/SW2"); - rest_activate_resource(&resource_switch_sw3, "DR1199/Switch/SW3"); - rest_activate_resource(&resource_switch_sw4, "DR1199/Switch/SW4"); - rest_activate_resource(&resource_switch_dio8, "DR1199/Switch/DIO8"); - rest_activate_resource(&resource_pot, "DR1199/Potentiometer"); - rest_activate_resource(&resource_led_d1, "DR1199/LED/D1"); - rest_activate_resource(&resource_led_d2, "DR1199/LED/D2"); - rest_activate_resource(&resource_led_d3, "DR1199/LED/D3"); - rest_activate_resource(&resource_led_d3_1174, "DR1199/LED/D3On1174"); - rest_activate_resource(&resource_led_d6_1174, "DR1199/LED/D6On1174"); - rest_activate_resource(&resource_led_all, "DR1199/LED/All"); - rest_activate_resource(&resource_sensors_dr1199, "DR1199/AllSensors"); + coap_engine_init(); + coap_activate_resource(&resource_switch_sw1, "DR1199/Switch/SW1"); + coap_activate_resource(&resource_switch_sw2, "DR1199/Switch/SW2"); + coap_activate_resource(&resource_switch_sw3, "DR1199/Switch/SW3"); + coap_activate_resource(&resource_switch_sw4, "DR1199/Switch/SW4"); + coap_activate_resource(&resource_switch_dio8, "DR1199/Switch/DIO8"); + coap_activate_resource(&resource_pot, "DR1199/Potentiometer"); + coap_activate_resource(&resource_led_d1, "DR1199/LED/D1"); + coap_activate_resource(&resource_led_d2, "DR1199/LED/D2"); + coap_activate_resource(&resource_led_d3, "DR1199/LED/D3"); + coap_activate_resource(&resource_led_d3_1174, "DR1199/LED/D3On1174"); + coap_activate_resource(&resource_led_d6_1174, "DR1199/LED/D6On1174"); + coap_activate_resource(&resource_led_all, "DR1199/LED/All"); + coap_activate_resource(&resource_sensors_dr1199, "DR1199/AllSensors"); /* If sensor process generates an event, call event_handler of resource. This will make this resource observable by the client */ while(1) { @@ -382,4 +380,3 @@ PROCESS_THREAD(start_app, ev, data) PROCESS_END(); } - diff --git a/examples/platform-specific/jn516x/rpl/coap-dr1199-node/project-conf.h b/examples/platform-specific/jn516x/rpl/coap-dr1199-node/project-conf.h index a46f32f1cbcfa265f1993120524fcd31ede09617..bb7d4d78501290d018d09f0e2a6b0f19f6be18d1 100644 --- a/examples/platform-specific/jn516x/rpl/coap-dr1199-node/project-conf.h +++ b/examples/platform-specific/jn516x/rpl/coap-dr1199-node/project-conf.h @@ -31,11 +31,11 @@ * \author Simon Duquennoy <simonduq@sics.se> */ -#ifndef __PROJECT_CONF_H__ -#define __PROJECT_CONF_H__ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ #define UIP_CONF_TCP 0 #include "../common-conf.h" -#endif /* __PROJECT_CONF_H__ */ +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/platform-specific/jn516x/rpl/node/Makefile b/examples/platform-specific/jn516x/rpl/node/Makefile index 37f6c7c79573785bfa5e148ecc7dd599b324fcb1..b5a14023a29e4be01da9900e443be64b297bf447 100644 --- a/examples/platform-specific/jn516x/rpl/node/Makefile +++ b/examples/platform-specific/jn516x/rpl/node/Makefile @@ -1,12 +1,13 @@ CONTIKI_PROJECT = node all: $(CONTIKI_PROJECT) +PLATFORMS_ONLY = jn516x + TARGET ?= jn516x CONTIKI=../../../../.. MAKE_MAC = MAKE_MAC_TSCH -PROJECTDIRS += .. ../tools -PROJECT_SOURCEFILES += rpl-tools.c +MODULES_REL += .. include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/jn516x/rpl/node/node.c b/examples/platform-specific/jn516x/rpl/node/node.c index 3c24f36c12601345c34e067b2735f8dbd502c8b0..71e015e6d4c35dfd3601bc0c67a5766adcee9458 100644 --- a/examples/platform-specific/jn516x/rpl/node/node.c +++ b/examples/platform-specific/jn516x/rpl/node/node.c @@ -37,8 +37,7 @@ #include "contiki.h" #include "net/ipv6/uip-ds6.h" -#include "rpl.h" -#include "tools/rpl-tools.h" +#include "net/routing/routing.h" #define DEBUG DEBUG_PRINT #include "net/ipv6/uip-debug.h" @@ -59,7 +58,6 @@ AUTOSTART_PROCESSES(&node_process); /*---------------------------------------------------------------------------*/ PROCESS_THREAD(node_process, ev, data) { - static struct etimer et; PROCESS_BEGIN(); /* 3 possible roles: @@ -73,6 +71,7 @@ PROCESS_THREAD(node_process, ev, data) #if CONFIG_VIA_BUTTON { #define CONFIG_WAIT_TIME 5 + static struct etimer et; SENSORS_ACTIVATE(button_sensor); etimer_set(&et, CLOCK_SECOND * CONFIG_WAIT_TIME); @@ -96,22 +95,10 @@ PROCESS_THREAD(node_process, ev, data) node_role == role_6ln ? "6ln" : "6dr"); is_coordinator = node_role > role_6ln; - if(is_coordinator) { - uip_ipaddr_t prefix; - uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); - rpl_tools_init(&prefix); - } else { - rpl_tools_init(NULL); - } - - /* Print out routing tables every minute */ - etimer_set(&et, CLOCK_SECOND * 60); - while(1) { - print_network_status(); - PROCESS_YIELD_UNTIL(etimer_expired(&et)); - etimer_reset(&et); + NETSTACK_ROUTING.root_start(); } + NETSTACK_MAC.on(); PROCESS_END(); } diff --git a/examples/platform-specific/jn516x/rpl/node/project-conf.h b/examples/platform-specific/jn516x/rpl/node/project-conf.h index 9db6f0229c5d5648b9ca695322a9da75b87c3d84..52adee3b96f29bcaf14fb960160fc6d7b873191b 100644 --- a/examples/platform-specific/jn516x/rpl/node/project-conf.h +++ b/examples/platform-specific/jn516x/rpl/node/project-conf.h @@ -32,9 +32,9 @@ * \author Simon Duquennoy <simonduq@sics.se> */ -#ifndef __PROJECT_CONF_H__ -#define __PROJECT_CONF_H__ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ #include "../common-conf.h" -#endif /* __PROJECT_CONF_H__ */ +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/platform-specific/jn516x/rpl/tools/rpl-tools.c b/examples/platform-specific/jn516x/rpl/tools/rpl-tools.c deleted file mode 100644 index 570be8566daf70449a5c86555b21df073404616a..0000000000000000000000000000000000000000 --- a/examples/platform-specific/jn516x/rpl/tools/rpl-tools.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2015, SICS Swedish ICT. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ -/** - * \file - * - * \author Simon Duquennoy <simonduq@sics.se> - */ - -#include "contiki.h" -#include "contiki-net.h" -#include "net/ipv6/uip.h" -#include "rpl.h" -#include "rpl-dag-root.h" -#include <string.h> -#include <stdio.h> - -#define DEBUG DEBUG_PRINT -#include "net/ipv6/uip-debug.h" - -/*---------------------------------------------------------------------------*/ -void -print_network_status(void) -{ - int i; - uint8_t state; - uip_ds6_defrt_t *default_route; - uip_ds6_route_t *route; - - PRINTA("--- Network status ---\n"); - - /* Our IPv6 addresses */ - PRINTA("- Server IPv6 addresses:\n"); - for(i = 0; i < UIP_DS6_ADDR_NB; i++) { - state = uip_ds6_if.addr_list[i].state; - if(uip_ds6_if.addr_list[i].isused && - (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { - PRINTA("-- "); - uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); - PRINTA("\n"); - } - } - - /* Our default route */ - PRINTA("- Default route:\n"); - default_route = uip_ds6_defrt_lookup(uip_ds6_defrt_choose()); - if(default_route != NULL) { - PRINTA("-- "); - uip_debug_ipaddr_print(&default_route->ipaddr);; - PRINTA(" (lifetime: %lu seconds)\n", (unsigned long)default_route->lifetime.interval); - } else { - PRINTA("-- None\n"); - } - - /* Our routing entries */ - PRINTA("- Routing entries (%u in total):\n", uip_ds6_route_num_routes()); - route = uip_ds6_route_head(); - while(route != NULL) { - PRINTA("-- "); - uip_debug_ipaddr_print(&route->ipaddr); - PRINTA(" via "); - uip_debug_ipaddr_print(uip_ds6_route_nexthop(route)); - PRINTA(" (lifetime: %lu seconds)\n", (unsigned long)route->state.lifetime); - route = uip_ds6_route_next(route); - } - - PRINTA("----------------------\n"); -} -/*---------------------------------------------------------------------------*/ -static void -print_local_addresses(void) -{ - int i; - uint8_t state; - - PRINTA("Server IPv6 addresses:\n"); - for(i = 0; i < UIP_DS6_ADDR_NB; i++) { - state = uip_ds6_if.addr_list[i].state; - if(uip_ds6_if.addr_list[i].isused && - (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { - PRINTA(" "); - uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); - PRINTA("\n"); - } - } -} -/*---------------------------------------------------------------------------*/ -void -rpl_tools_init(uip_ipaddr_t *br_prefix) -{ - if(br_prefix) { /* We are root */ - rpl_dag_root_init(br_prefix, NULL); - rpl_dag_root_init_dag_immediately(); - } else { - rpl_dag_root_init(NULL, NULL); - } - - - NETSTACK_MAC.on(); - - print_local_addresses(); -} diff --git a/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/Makefile b/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/Makefile index df37a89afcece25dd9a2859cceae627c70c579d5..2880a76dedb9500eb50509d8476d5d24b8413e22 100644 --- a/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/Makefile +++ b/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/Makefile @@ -1,12 +1,13 @@ CONTIKI_PROJECT = node +PLATFORMS_ONLY = jn516x + TARGET ?= jn516x JN516x_WITH_DONGLE = 1 CONTIKI=../../../../../.. -PROJECTDIRS += .. ../../tools -PROJECT_SOURCEFILES += rpl-tools.c +MODULES_REL += .. MAKE_MAC = MAKE_MAC_TSCH MODULES += os/net/app-layer/coap MODULES += os/services/orchestra os/lib/json diff --git a/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/node.c b/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/node.c index 0b1bc3414e87e53690b23c0d9779546c228f85fe..42fa11fb74c31b0c27fcac70ed824a2e77ff6dc7 100644 --- a/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/node.c +++ b/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/node.c @@ -34,17 +34,10 @@ #include "contiki.h" #include "net/netstack.h" -#include "net/mac/tsch/tsch-schedule.h" #include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-private.h" -#include "rpl.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ -#include "net/mac/tsch/tsch-schedule.h" +#include "net/routing/routing.h" #include "net/ipv6/uip-debug.h" #include "lib/random.h" -#include "rpl-tools.h" #include "node-id.h" #include "waveform.h" #include "leds.h" @@ -173,12 +166,9 @@ PROCESS_THREAD(node_process, ev, data) is_coordinator = node_role > role_6ln; if(is_coordinator) { - uip_ipaddr_t prefix; - uip_ip6addr(&prefix, 0xbbbb, 0, 0, 0, 0, 0, 0, 0); - rpl_tools_init(&prefix); - } else { - rpl_tools_init(NULL); + NETSTACK_ROUTING.root_start(); } + NETSTACK_MAC.on(); /* Selected waveform depends on LS byte of MAC */ selected_waveform = node_mac[7] % NUMBER_OF_WAVEFORMS; @@ -214,10 +204,6 @@ PROCESS_THREAD(node_process, ev, data) printf("No host\n"); } etimer_restart(&et); - if (total_time%60 == 0) { - /* Print network status once per minute */ - print_network_status(); - } } } PROCESS_END(); diff --git a/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/project-conf.h b/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/project-conf.h index 360fdef259e820ae70e4a3eff287d74fcf3dbedb..65ddcef467aca0ddcbe64efbbf027147d6626d7d 100644 --- a/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/project-conf.h +++ b/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/project-conf.h @@ -32,12 +32,12 @@ * */ -#ifndef __PROJECT_CONF_H__ -#define __PROJECT_CONF_H__ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ #define UIP_CONF_TCP 0 #define UART_BAUD_RATE UART_RATE_115200 #include "../../common-conf.h" -#endif /* __PROJECT_CONF_H__ */ +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/platform-specific/jn516x/tsch/tools/rpl-tools.c b/examples/platform-specific/jn516x/tsch/tools/rpl-tools.c deleted file mode 100644 index e71a19bc955c947d8665772851d9d0511a14fe85..0000000000000000000000000000000000000000 --- a/examples/platform-specific/jn516x/tsch/tools/rpl-tools.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2014, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ -/** - * \file - * - * \author Simon Duquennoy <simonduq@sics.se> - */ - -#include "contiki.h" -#include "contiki-net.h" -#include "net/ipv6/uip.h" -#include "rpl.h" -#include "rpl-dag-root.h" -#include <string.h> -#include <stdio.h> - -#define DEBUG DEBUG_PRINT -#include "net/ipv6/uip-debug.h" - -void -print_network_status(void) -{ - int i; - uint8_t state; - uip_ds6_defrt_t *default_route; - uip_ds6_route_t *route; - PRINTA("--- Network status ---\n"); - /* Our IPv6 addresses */ - PRINTA("- Server IPv6 addresses:\n"); - for(i = 0; i < UIP_DS6_ADDR_NB; i++) { - state = uip_ds6_if.addr_list[i].state; - if(uip_ds6_if.addr_list[i].isused && - (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { - PRINTA("-- "); - uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); - PRINTA("\n"); - } - } - /* Our default route */ - PRINTA("- Default route:\n"); - default_route = uip_ds6_defrt_lookup(uip_ds6_defrt_choose()); - if(default_route != NULL) { - PRINTA("-- "); - uip_debug_ipaddr_print(&default_route->ipaddr);; - PRINTA(" (lifetime: %lu seconds)\n", (unsigned long)default_route->lifetime.interval); - } else { - PRINTA("-- None\n"); - } - /* Our routing entries */ - PRINTA("- Routing entries (%u in total):\n", uip_ds6_route_num_routes()); - route = uip_ds6_route_head(); - while(route != NULL) { - PRINTA("-- "); - uip_debug_ipaddr_print(&route->ipaddr); - PRINTA(" via "); - uip_debug_ipaddr_print(uip_ds6_route_nexthop(route)); - PRINTA(" (lifetime: %lu seconds)\n", (unsigned long)route->state.lifetime); - route = uip_ds6_route_next(route); - } - PRINTA("----------------------\n"); -} -/*---------------------------------------------------------------------------*/ -static void -print_local_addresses(void) -{ - int i; - uint8_t state; - - PRINTA("Server IPv6 addresses:\n"); - for(i = 0; i < UIP_DS6_ADDR_NB; i++) { - state = uip_ds6_if.addr_list[i].state; - if(uip_ds6_if.addr_list[i].isused && - (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { - PRINTA(" "); - uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); - PRINTA("\n"); - } - } -} -/*---------------------------------------------------------------------------*/ -void -rpl_tools_init(uip_ipaddr_t *br_prefix) -{ - if(br_prefix) { /* We are root */ - rpl_dag_root_init(br_prefix, NULL); - rpl_dag_root_init_dag_immediately(); - } else { - rpl_dag_root_init(NULL, NULL); - } - - /* Start TSCH */ - NETSTACK_MAC.on(); - print_local_addresses(); -} diff --git a/examples/platform-specific/jn516x/tsch/tx-power-verification/node/Makefile b/examples/platform-specific/jn516x/tsch/tx-power-verification/node/Makefile index 97721070242162d4e6f4d583f05aabedd1b8feb0..d19228f4dd9ad80c318af391faeec6a8e46b252d 100644 --- a/examples/platform-specific/jn516x/tsch/tx-power-verification/node/Makefile +++ b/examples/platform-specific/jn516x/tsch/tx-power-verification/node/Makefile @@ -1,12 +1,13 @@ CONTIKI_PROJECT = node +PLATFORMS_ONLY = jn516x + TARGET ?= jn516x JN516x_WITH_DONGLE = 1 CONTIKI=../../../../../.. -PROJECTDIRS += .. ../../tools -PROJECT_SOURCEFILES += rpl-tools.c +MODULES_REL += .. MAKE_MAC = MAKE_MAC_TSCH MODULES += os/net/app-layer/coap diff --git a/examples/platform-specific/jn516x/tsch/tx-power-verification/node/node.c b/examples/platform-specific/jn516x/tsch/tx-power-verification/node/node.c index 115649535359b0de281cf5a667f63d2384ce8fcb..995dc33047b39af23151f600f5549ce61b845802 100644 --- a/examples/platform-specific/jn516x/tsch/tx-power-verification/node/node.c +++ b/examples/platform-specific/jn516x/tsch/tx-power-verification/node/node.c @@ -33,19 +33,19 @@ */ #include "contiki.h" #include "net/ipv6/uip-ds6.h" +#include "net/routing/routing.h" #include "net/netstack.h" #include "net/ipv6/uip.h" #include "net/linkaddr.h" -#include "rpl-tools.h" -#include "rest-engine.h" -#include <stdio.h> -#include <stdlib.h> +#include "coap-engine.h" +#include <stdio.h> +#include <stdlib.h> #include <AppHardwareApi.h> -static void set_tx_power_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_tx_power_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void set_tx_power_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_tx_power_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static char content[REST_MAX_CHUNK_SIZE]; +static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; #define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) content_len += snprintf(content+content_len, sizeof(content)-content_len, __VA_ARGS__); } @@ -56,45 +56,45 @@ AUTOSTART_PROCESSES(&start_app); /*---------------------------------------------------------------------------*/ /*********** sensor/ resource ************************************************/ -RESOURCE(resource_set_tx_power, +RESOURCE(resource_set_tx_power, "title=\"Set TX Power\"", NULL, set_tx_power_handler, set_tx_power_handler, NULL); static void -set_tx_power_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +set_tx_power_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content = NULL; int tx_level; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); tx_level = atoi((const char *)request_content); NETSTACK_RADIO.set_value(RADIO_PARAM_TXPOWER, tx_level); } } -RESOURCE(resource_get_tx_power, +RESOURCE(resource_get_tx_power, "title=\"Get TX Power\"", get_tx_power_handler, NULL, NULL, NULL); static void -get_tx_power_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_tx_power_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int tx_level; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; NETSTACK_RADIO.get_value(RADIO_PARAM_TXPOWER, &tx_level); CONTENT_PRINTF("%d", tx_level); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } /*---------------------------------------------------------------------------*/ @@ -102,20 +102,17 @@ PROCESS_THREAD(start_app, ev, data) { PROCESS_BEGIN(); static int is_coordinator = 0; - + /* Start network stack */ if(is_coordinator) { - uip_ipaddr_t prefix; - uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); - rpl_tools_init(&prefix); - } else { - rpl_tools_init(NULL); + NETSTACK_ROUTING.root_start(); } + NETSTACK_MAC.on(); printf("Starting RPL node\n"); - - rest_init_engine(); - rest_activate_resource(&resource_set_tx_power, "Set-TX-Power"); - rest_activate_resource(&resource_get_tx_power, "Get-TX-Power"); + + coap_engine_init(); + coap_activate_resource(&resource_set_tx_power, "Set-TX-Power"); + coap_activate_resource(&resource_get_tx_power, "Get-TX-Power"); PROCESS_END(); } diff --git a/examples/platform-specific/jn516x/tsch/tx-power-verification/node/project-conf.h b/examples/platform-specific/jn516x/tsch/tx-power-verification/node/project-conf.h index 0394b0ad5aed2ac1c1706151ce2a1256094b047d..94e17dc1c95b4e1339fbb13014d9731cbc144f03 100644 --- a/examples/platform-specific/jn516x/tsch/tx-power-verification/node/project-conf.h +++ b/examples/platform-specific/jn516x/tsch/tx-power-verification/node/project-conf.h @@ -31,12 +31,12 @@ * \author Simon Duquennoy <simonduq@sics.se> */ -#ifndef __PROJECT_CONF_H__ -#define __PROJECT_CONF_H__ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ #define UIP_CONF_TCP 0 #define UART_BAUD_RATE UART_RATE_115200 #include "../../common-conf.h" -#endif /* __PROJECT_CONF_H__ */ +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/Makefile b/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/Makefile deleted file mode 100644 index c88fa5a2be4ad3f17b5986ef418aa74fbbd4bc0e..0000000000000000000000000000000000000000 --- a/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -CONTIKI_PROJECT=rpl-border-router - -TARGET ?= jn516x -JN516x_WITH_DONGLE = 1 - -CONTIKI=../../../../../.. - -PROJECT_SOURCEFILES += slip-bridge.c slip.c - -PROJECTDIRS += .. ../../tools -PROJECT_SOURCEFILES += rpl-tools.c - -MAKE_MAC = MAKE_MAC_TSCH -MODULES += os/net/app-layer/coap -MODULES += os/services/orchestra os/lib/json - -all: $(CONTIKI_PROJECT) -include $(CONTIKI)/Makefile.include - -ifeq ($(PREFIX),) - PREFIX = aaaa::1/64 -endif - -#no flow control -connect-router: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 -v1 -B 1000000 $(PREFIX) - -#using XON/XOFF flow control -connect-router-sw: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 -v1 -X -B 1000000 $(PREFIX) - -#using hw flow control -connect-router-hw: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 -v1 -H -B 1000000 $(PREFIX) - -#using no flow control -connect-router-no: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 -v1 -B 1000000 $(PREFIX) - -connect-router-cooja: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 $(PREFIX) diff --git a/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/rpl-border-router.c b/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/rpl-border-router.c deleted file mode 100644 index e15a779895df37f0a9c83dd24b56b80d68402802..0000000000000000000000000000000000000000 --- a/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/rpl-border-router.c +++ /dev/null @@ -1,169 +0,0 @@ -/* -* Copyright (c) 2015 NXP B.V. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. Neither the name of NXP B.V. nor the names of its contributors -* may be used to endorse or promote products derived from this software -* without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY NXP B.V. AND CONTRIBUTORS ``AS IS'' AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL NXP B.V. OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -* SUCH DAMAGE. -* -* This file is part of the Contiki operating system. -* -* Author: Theo van Daele <theo.van.daele@nxp.com> -* -*/ -#include "contiki.h" -#include "contiki-lib.h" -#include "contiki-net.h" -#include "net/ipv6/uip.h" -#include "net/ipv6/uip-ds6.h" -#include "rpl.h" -#include "simple-udp.h" -#include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-schedule.h" -#include "net/netstack.h" -#include "dev/slip.h" -#include "rest-engine.h" -#include "rpl-tools.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> - -#define DEBUG DEBUG_NONE -#include "net/ipv6/uip-debug.h" - -static uip_ipaddr_t prefix; -static uint8_t prefix_set; - -static void get_rssi_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void get_last_rssi_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); - -static char content[REST_MAX_CHUNK_SIZE]; -static int content_len = 0; - -#define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) content_len += snprintf(content+content_len, sizeof(content)-content_len, __VA_ARGS__); } - -PROCESS(border_router_process, "Border router process"); -AUTOSTART_PROCESSES(&border_router_process); - -RESOURCE(resource_get_rssi, - "title=\"Get RSSI\"", - get_rssi_handler, - NULL, - NULL, - NULL); -static void -get_rssi_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) -{ - int rssi_level; - unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - content_len = 0; - NETSTACK_RADIO.get_value(RADIO_PARAM_RSSI, &rssi_level); - CONTENT_PRINTF("%d", rssi_level); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); - } -} - -RESOURCE(resource_get_last_rssi, - "title=\"Get last RSSI\"", - get_last_rssi_handler, - NULL, - NULL, - NULL); -static void -get_last_rssi_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) -{ - int last_rssi_level; - unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - content_len = 0; - NETSTACK_RADIO.get_value(RADIO_PARAM_LAST_RSSI, &last_rssi_level); - CONTENT_PRINTF("%d", last_rssi_level); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); - } -} - -/*---------------------------------------------------------------------------*/ -void -request_prefix(void) -{ - /* mess up uip_buf with a dirty request... */ - uip_buf[0] = '?'; - uip_buf[1] = 'P'; - uip_len = 2; - slip_send(); - uip_len = 0; -} -/*---------------------------------------------------------------------------*/ -void -set_prefix_64(uip_ipaddr_t *prefix_64) -{ - memcpy(&prefix, prefix_64, 16); - prefix_set = 1; -} -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(border_router_process, ev, data) -{ - static struct etimer et; - - PROCESS_BEGIN(); - -/* While waiting for the prefix to be sent through the SLIP connection, the future - * border router can join an existing DAG as a parent or child, or acquire a default - * router that will later take precedence over the SLIP fallback interface. - * Prevent that by turning the radio off until we are initialized as a DAG root. - */ - prefix_set = 0; - - PROCESS_PAUSE(); - - PRINTF("RPL-Border router started\n"); - - /* Request prefix until it has been received */ - while(!prefix_set) { - etimer_set(&et, CLOCK_SECOND); - request_prefix(); - PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); - PRINTF("Waiting for prefix\n"); - } - - PRINTF("Obtained prefix: "); - uip_debug_ipaddr_print(&prefix); - PRINTF("\n"); - - rpl_tools_init(&prefix); - - rest_init_engine(); - rest_activate_resource(&resource_get_rssi, "Get-RSSI"); - rest_activate_resource(&resource_get_last_rssi, "Get-Last-RSSI"); - - - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/slip-bridge.c b/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/slip-bridge.c deleted file mode 100644 index 8201bf0f751ae72890707cb7b5322bce70d984e1..0000000000000000000000000000000000000000 --- a/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/slip-bridge.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -/** - * \file - * Slip fallback interface - * \author - * Niclas Finne <nfi@sics.se> - * Joakim Eriksson <joakime@sics.se> - * Joel Hoglund <joel@sics.se> - * Nicolas Tsiftes <nvt@sics.se> - */ - -#include "net/ipv6/uip.h" -#include "net/ipv6/uip-ds6.h" -#include "dev/slip.h" -#if CONTIKI_TARGET_JN516X -#include "dev/uart0.h" -#else -#include "dev/uart1.h" -#endif -#include <string.h> - -#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) - -#define DEBUG DEBUG_NONE -#include "net/ipv6/uip-debug.h" - -void set_prefix_64(uip_ipaddr_t *); - -static uip_ipaddr_t last_sender; -/*---------------------------------------------------------------------------*/ -static void -slip_input_callback(void) -{ - PRINTF("SIN: %u\n", uip_len); - if(uip_buf[0] == '!') { - PRINTF("Got configuration message of type %c\n", uip_buf[1]); - uip_len = 0; - if(uip_buf[1] == 'P') { - uip_ipaddr_t prefix; - /* Here we set a prefix !!! */ - memset(&prefix, 0, 16); - memcpy(&prefix, &uip_buf[2], 8); - PRINTF("Setting prefix "); - PRINT6ADDR(&prefix); - PRINTF("\n"); - set_prefix_64(&prefix); - } - } else if (uip_buf[0] == '?') { - PRINTF("Got request message of type %c\n", uip_buf[1]); - if(uip_buf[1] == 'M') { - char* hexchar = "0123456789abcdef"; - int j; - /* this is just a test so far... just to see if it works */ - uip_buf[0] = '!'; - for(j = 0; j < 8; j++) { - uip_buf[2 + j * 2] = hexchar[uip_lladdr.addr[j] >> 4]; - uip_buf[3 + j * 2] = hexchar[uip_lladdr.addr[j] & 15]; - } - uip_len = 18; - slip_send(); - - } - uip_len = 0; - } - /* Save the last sender received over SLIP to avoid bouncing the - packet back if no route is found */ - uip_ipaddr_copy(&last_sender, &UIP_IP_BUF->srcipaddr); -} -/*---------------------------------------------------------------------------*/ -static void -init(void) -{ - slip_arch_init(); - process_start(&slip_process, NULL); - slip_set_input_callback(slip_input_callback); -} -/*---------------------------------------------------------------------------*/ -static int -output(void) -{ - if(uip_ipaddr_cmp(&last_sender, &UIP_IP_BUF->srcipaddr)) { - /* Do not bounce packets back over SLIP if the packet was received - over SLIP */ - PRINTF("slip-bridge: Destination off-link but no route src="); - PRINT6ADDR(&UIP_IP_BUF->srcipaddr); - PRINTF(" dst="); - PRINT6ADDR(&UIP_IP_BUF->destipaddr); - PRINTF("\n"); - } else { - PRINTF("SUT: %u\n", uip_len); - slip_send(); - printf("\n"); - } - return 0; -} - -/*---------------------------------------------------------------------------*/ -#if !SLIP_BRIDGE_CONF_NO_PUTCHAR -#undef putchar -int -putchar(int c) -{ -#define SLIP_END 0300 - static char debug_frame = 0; - - if(!debug_frame) { /* Start of debug output */ - slip_arch_writeb(SLIP_END); - slip_arch_writeb('\r'); /* Type debug line == '\r' */ - debug_frame = 1; - } - - /* Need to also print '\n' because for example COOJA will not show - any output before line end */ - slip_arch_writeb((char)c); - - /* - * Line buffered output, a newline marks the end of debug output and - * implicitly flushes debug output. - */ - if(c == '\n') { - slip_arch_writeb(SLIP_END); - debug_frame = 0; - } - return c; -} -#endif -/*---------------------------------------------------------------------------*/ -const struct uip_fallback_interface rpl_interface = { - init, output -}; -/*---------------------------------------------------------------------------*/ diff --git a/examples/platform-specific/jn516x/tsch/uart1-test-node/Makefile b/examples/platform-specific/jn516x/tsch/uart1-test-node/Makefile index ca520969d0908e7a9e6018ac606991f016ce4a04..22c5ee2164792f73f3f9367ca9fc99516c70cea9 100644 --- a/examples/platform-specific/jn516x/tsch/uart1-test-node/Makefile +++ b/examples/platform-specific/jn516x/tsch/uart1-test-node/Makefile @@ -1,13 +1,14 @@ CONTIKI_PROJECT = uart1-test-node +PLATFORMS_ONLY = jn516x + TARGET = jn516x JN516x_WITH_DR1174 = 1 TARGET_WITH_UART1 = 1 CONTIKI=../../../../.. -PROJECTDIRS += .. ../tools -PROJECT_SOURCEFILES += rpl-tools.c +MODULES_REL += .. MAKE_MAC = MAKE_MAC_TSCH MODULES += os/net/app-layer/coap diff --git a/examples/platform-specific/jn516x/tsch/uart1-test-node/project-conf.h b/examples/platform-specific/jn516x/tsch/uart1-test-node/project-conf.h index 373ea0f2785504dcb458dae6c18bf6ddaf001344..d833869bbf88a9774d4b2d56651d187dabb6dc4b 100644 --- a/examples/platform-specific/jn516x/tsch/uart1-test-node/project-conf.h +++ b/examples/platform-specific/jn516x/tsch/uart1-test-node/project-conf.h @@ -31,8 +31,8 @@ * \author Simon Duquennoy <simonduq@sics.se> */ -#ifndef __PROJECT_CONF_H__ -#define __PROJECT_CONF_H__ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ #define UIP_CONF_TCP 0 @@ -46,4 +46,4 @@ #include "../common-conf.h" -#endif /* __PROJECT_CONF_H__ */ +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/platform-specific/jn516x/tsch/uart1-test-node/uart1-test-node.c b/examples/platform-specific/jn516x/tsch/uart1-test-node/uart1-test-node.c index 244672d4893e4926533bf494b503167e0236b6a5..dd647fa218be2e474d30756130075b38442100ec 100644 --- a/examples/platform-specific/jn516x/tsch/uart1-test-node/uart1-test-node.c +++ b/examples/platform-specific/jn516x/tsch/uart1-test-node/uart1-test-node.c @@ -34,24 +34,24 @@ #include "contiki.h" #include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip.h" +#include "net/routing/routing.h" #include "net/linkaddr.h" -#include "rpl-tools.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "sys/ctimer.h" #include "dev/uart-driver.h" #include "uart1.h" #include <AppHardwareApi.h> -static void get_coap_rx_uart1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_coap_rx_uart1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void event_coap_rx_uart1_handler(void); -static void put_post_tx_uart1_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void put_post_tx_uart1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void string2uart1(uint8_t *c); static int handleRxChar(uint8_t c); static int get_ringbuf(uint8_t *c); static int put_ringbuf(uint8_t c); /* COAP helpers */ -static char content[REST_MAX_CHUNK_SIZE]; +static char content[COAP_MAX_CHUNK_SIZE]; static int content_len = 0; #define CONTENT_PRINTF(...) { if(content_len < sizeof(content)) content_len += snprintf(content+content_len, sizeof(content)-content_len, __VA_ARGS__); } @@ -64,7 +64,7 @@ static int tail_index = 0; /* index where last read took place */ /* String aligned buffer */ #define RX_BUFFER_SIZE RINGBUF_SIZE -static uint8_t rx_buf[RX_BUFFER_SIZE+1]; +static uint8_t rx_buf[RX_BUFFER_SIZE+1]; static uint8_t rx_buf_index = 0; /* index for rx_buf */ /*---------------------------------------------------------------------------*/ @@ -75,7 +75,7 @@ AUTOSTART_PROCESSES(&start_app, &rx_data_process); /*********** COAP resources *************************************************/ /*****************************************************************************/ -/* Observable resource and event handler to obtain terminal input from UART1 */ +/* Observable resource and event handler to obtain terminal input from UART1 */ /*****************************************************************************/ EVENT_RESOURCE(resource_coap_rx_uart1, /* name */ "obs;title=\"rx_uart1\"", /* attributes */ @@ -85,27 +85,27 @@ EVENT_RESOURCE(resource_coap_rx_uart1, /* name */ NULL, /* DELETE handler */ event_coap_rx_uart1_handler); /* event handler */ static void -get_coap_rx_uart1_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +get_coap_rx_uart1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { content_len = 0; CONTENT_PRINTF("%s", rx_buf); - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, (uint8_t *)content, content_len); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } -} +} static void event_coap_rx_uart1_handler(void) { /* Registered observers are notified and will trigger the GET handler to create the response. */ - REST.notify_subscribers(&resource_coap_rx_uart1); + coap_notify_observers(&resource_coap_rx_uart1); } /*****************************************************************************/ -/* GET/PUT resource to send data to terminal on UART1 */ +/* GET/PUT resource to send data to terminal on UART1 */ /*****************************************************************************/ RESOURCE(resource_coap_tx_uart1, /* name */ "obs;title=\"tx_uart1\"", /* attributes */ @@ -115,14 +115,14 @@ RESOURCE(resource_coap_tx_uart1, /* name */ NULL); /* DELETE handler */ static void -put_post_tx_uart1_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +put_post_tx_uart1_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *request_content = NULL; unsigned int accept = -1; - REST.get_header_accept(request, &accept); - if(accept == -1 || accept == REST.type.TEXT_PLAIN) { - REST.get_request_payload(request, &request_content); + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == TEXT_PLAIN) { + coap_get_payload(request, &request_content); string2uart1((uint8_t *)request_content); } } @@ -140,23 +140,20 @@ PROCESS_THREAD(start_app, ev, data) /* Define process that handles data */ process_start(&rx_data_process ,NULL); /* Initialise UART1 */ - uart1_init(UART1_BAUD_RATE); + uart1_init(UART1_BAUD_RATE); /* Callback received byte */ uart1_set_input(handleRxChar); /* Start network stack */ if(is_coordinator) { - uip_ipaddr_t prefix; - uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); - rpl_tools_init(&prefix); - } else { - rpl_tools_init(NULL); + NETSTACK_ROUTING.root_start(); } + NETSTACK_MAC.on(); printf("Starting RPL node\n"); - - rest_init_engine(); - rest_activate_resource(&resource_coap_rx_uart1, "UART1-RX"); - rest_activate_resource(&resource_coap_tx_uart1, "UART1-TX"); + + coap_engine_init(); + coap_activate_resource(&resource_coap_rx_uart1, "UART1-RX"); + coap_activate_resource(&resource_coap_tx_uart1, "UART1-TX"); PROCESS_END(); } @@ -166,29 +163,29 @@ PROCESS_THREAD(start_app, ev, data) PROCESS_THREAD(rx_data_process, ev, data) { PROCESS_BEGIN(); - + /* Process is polled whenever data is available from uart isr */ uint8_t c; while(1) { PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL); - /* Read RX ringbuffer. ASCII chars Output when LF is seen. - If overflowed, strings are skipped */ + /* Read RX ringbuffer. ASCII chars Output when LF is seen. + If overflowed, strings are skipped */ do { if (get_ringbuf(&c) == -1) { break; /* No more rx char's in ringbuffer */ } else { if (rx_buf_index == RX_BUFFER_SIZE) { /* Skip current content if buffer full */ rx_buf_index = 0; - } + } rx_buf[rx_buf_index++] = c; if ((c == '\n')||(c == '\r')) { rx_buf[rx_buf_index] = '\0'; - printf("RX on UART1: %s", rx_buf); + printf("RX on UART1: %s", rx_buf); /* Signal event to coap clients. Demo assumes data is consumed before new data comes in */ - event_coap_rx_uart1_handler(); - rx_buf_index = 0; + event_coap_rx_uart1_handler(); + rx_buf_index = 0; } } } while (1); @@ -200,7 +197,7 @@ PROCESS_THREAD(rx_data_process, ev, data) /* Local test functions */ /*************************************************************************/ /* TX function for UART1 */ -static void +static void string2uart1(uint8_t *c) { while (*c!= '\0') { @@ -210,7 +207,7 @@ string2uart1(uint8_t *c) } /* handleRxChar runs on uart isr */ -static int +static int handleRxChar(uint8_t c) { if (put_ringbuf(c) == -1) { @@ -225,7 +222,7 @@ handleRxChar(uint8_t c) /* Simple ringbuffer if tail==head, no data has been written yet on that position. So, empty buffer is also initial state */ -static int +static int get_ringbuf(uint8_t *c) { int return_val = 0; @@ -241,7 +238,7 @@ get_ringbuf(uint8_t *c) return return_val; } -static int +static int put_ringbuf(uint8_t c) { int return_val = 0; @@ -249,11 +246,10 @@ put_ringbuf(uint8_t c) uart1_disable_interrupts(); if (head_index != tail_index) { ringbuf[head_index] = c; - head_index = ((head_index+1)&RINGBUF_MAX_INDEX); + head_index = ((head_index+1)&RINGBUF_MAX_INDEX); } else { return_val = -1; } uart1_enable_interrupts(); - return return_val; + return return_val; } - diff --git a/examples/platform-specific/nrf52dk/blink-hello/Makefile b/examples/platform-specific/nrf52dk/blink-hello/Makefile index d5d2de18d3bd752598a7e1bd6640c9a2bd7c0329..393a385c3560bf002e47dac3783d96b83c21933e 100644 --- a/examples/platform-specific/nrf52dk/blink-hello/Makefile +++ b/examples/platform-specific/nrf52dk/blink-hello/Makefile @@ -1,10 +1,12 @@ CONTIKI_PROJECT = blink-hello -MAKE_ROUTING = MAKE_ROUTING_NONE +MAKE_ROUTING = MAKE_ROUTING_NULLROUTING MAKE_MAC=MAKE_MAC_NULLMAC NRF52_WITHOUT_SOFTDEVICE=1 all: $(CONTIKI_PROJECT) +PLATFORMS_ONLY = nrf52dk + CONTIKI = ../../../.. include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/nrf52dk/coap-demo/Makefile b/examples/platform-specific/nrf52dk/coap-demo/Makefile deleted file mode 100644 index 6d9639da0a4aa77b0295d204a0ae7a9fff029329..0000000000000000000000000000000000000000 --- a/examples/platform-specific/nrf52dk/coap-demo/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -CONTIKI=../../../.. - -ifeq ($(MAKECMDGOALS),) -$(error Please specify whether coap-client or coap-server should be built) -endif - -ifneq ($(filter coap-client coap-client.flash, $(MAKECMDGOALS)),) -ifeq ($(SERVER_IPV6_ADDR),) -$(error Please define SERVER_IPV6_ADDR=<full ipv6 addr>) -else -CFLAGS += -DSERVER_IPV6_ADDR=\"$(SERVER_IPV6_ADDR)\" -CFLAGS += -DDEVICE_NAME=\"nRF52_DK_CoAP_Client\" -endif -else -CFLAGS += -DDEVICE_NAME=\"nRF52-DK-CoAP-Server\" -endif - -# automatically build RESTful resources -REST_RESOURCES_DIR = ./resources -REST_RESOURCES_FILES = $(notdir $(shell find $(REST_RESOURCES_DIR) -name '*.c' ! -name 'res-plugtest*')) - -PROJECTDIRS += $(REST_RESOURCES_DIR) -PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES) - -# REST Engine shall use Erbium CoAP implementation -MODULES += os/net/app-layer/coap - -MAKE_ROUTING = MAKE_ROUTING_NONE - -include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/nrf52dk/coap-demo/coap-client/Makefile b/examples/platform-specific/nrf52dk/coap-demo/coap-client/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b7a5ff778242706643b2ed438552f1c42ed52209 --- /dev/null +++ b/examples/platform-specific/nrf52dk/coap-demo/coap-client/Makefile @@ -0,0 +1,28 @@ +CONTIKI_PROJECT = coap-client +CONTIKI=../../../../.. + +PLATFORMS_ONLY = nrf52dk + +ifeq ($(SERVER_IPV6_EP),) +$(warning Please define SERVER_IPV6_EP=<full-coap-IPv6-URI>) +$(warning Using default SERVER_IPV6_EP=fd00::1) +SERVER_IPV6_EP=fd00::1 +endif + +CFLAGS += -DSERVER_IPV6_EP=\"$(SERVER_IPV6_EP)\" + +CFLAGS += -DDEVICE_NAME=\"nRF52_DK_CoAP_Client\" + +CFLAGS += -DCOAP_OBSERVE_CLIENT=1 + +# automatically build RESTful resources +MODULES_REL += ./resources + +# REST Engine shall use Erbium CoAP implementation +MODULES += os/net/app-layer/coap + +MAKE_ROUTING = MAKE_ROUTING_NULLROUTING + +all: $(CONTIKI_PROJECT) + +include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/nrf52dk/coap-demo/Makefile.target b/examples/platform-specific/nrf52dk/coap-demo/coap-client/Makefile.target similarity index 100% rename from examples/platform-specific/nrf52dk/coap-demo/Makefile.target rename to examples/platform-specific/nrf52dk/coap-demo/coap-client/Makefile.target diff --git a/examples/platform-specific/nrf52dk/coap-demo/coap-client.c b/examples/platform-specific/nrf52dk/coap-demo/coap-client/coap-client.c similarity index 95% rename from examples/platform-specific/nrf52dk/coap-demo/coap-client.c rename to examples/platform-specific/nrf52dk/coap-demo/coap-client/coap-client.c index 1ef59b36909db2bff2b80662d62a8141e1e957bd..4effcc87655f3266b7a157cdfe07bbbe522d094c 100644 --- a/examples/platform-specific/nrf52dk/coap-demo/coap-client.c +++ b/examples/platform-specific/nrf52dk/coap-demo/coap-client/coap-client.c @@ -51,6 +51,7 @@ #include "contiki.h" #include "contiki-net.h" #include "coap-engine.h" +#include "coap-endpoint.h" #include "dev/button-sensor.h" #include "dev/leds.h" @@ -63,13 +64,11 @@ #endif /*----------------------------------------------------------------------------*/ -#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) #define OBS_RESOURCE_URI "lights/led3" #define SUBS_LED LEDS_4 #define OBS_LED LEDS_3 /*----------------------------------------------------------------------------*/ -static uip_ipaddr_t server_ipaddr[1]; /* holds the server ip address */ static coap_observee_t *obs; static struct ctimer ct; /*----------------------------------------------------------------------------*/ @@ -146,11 +145,11 @@ notification_callback(coap_observee_t *obs, void *notification, PROCESS_THREAD(er_example_observe_client, ev, data) { PROCESS_BEGIN(); - - uiplib_ipaddrconv(SERVER_IPV6_ADDR, server_ipaddr); + static coap_endpoint_t server_endpoint; + coap_endpoint_parse(SERVER_IPV6_EP, strlen(SERVER_IPV6_EP), &server_endpoint); /* receives all CoAP messages */ - coap_init_engine(); + coap_engine_init(); #if PLATFORM_HAS_BUTTON SENSORS_ACTIVATE(button_1); @@ -164,7 +163,7 @@ PROCESS_THREAD(er_example_observe_client, ev, data) if (ev == sensors_event) { if (data == &button_1 && button_1.value(BUTTON_SENSOR_VALUE_STATE) == 0) { PRINTF("Starting observation\n"); - obs = coap_obs_request_registration(server_ipaddr, REMOTE_PORT, + obs = coap_obs_request_registration(&server_endpoint, OBS_RESOURCE_URI, notification_callback, NULL); } diff --git a/examples/platform-specific/nrf52dk/coap-demo/coap-server/Makefile b/examples/platform-specific/nrf52dk/coap-demo/coap-server/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..0202f0e929706d3ac1d956ac71f874c710b15c96 --- /dev/null +++ b/examples/platform-specific/nrf52dk/coap-demo/coap-server/Makefile @@ -0,0 +1,22 @@ +CONTIKI_PROJECT = coap-server +CONTIKI=../../../../.. + +PLATFORMS_ONLY = nrf52dk + +CFLAGS += -DDEVICE_NAME=\"nRF52-DK-CoAP-Server\" + +# automatically build RESTful resources +REST_RESOURCES_DIR = ../resources +REST_RESOURCES_FILES = $(notdir $(shell find $(REST_RESOURCES_DIR) -name '*.c' ! -name 'res-plugtest*')) + +PROJECTDIRS += $(REST_RESOURCES_DIR) +PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES) + +# REST Engine shall use Erbium CoAP implementation +MODULES += os/net/app-layer/coap + +MAKE_ROUTING = MAKE_ROUTING_NULLROUTING + +all: $(CONTIKI_PROJECT) + +include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/nrf52dk/coap-demo/coap-server/Makefile.target b/examples/platform-specific/nrf52dk/coap-demo/coap-server/Makefile.target new file mode 100644 index 0000000000000000000000000000000000000000..3853b313a1c152b862b9dde386f98425629434a2 --- /dev/null +++ b/examples/platform-specific/nrf52dk/coap-demo/coap-server/Makefile.target @@ -0,0 +1 @@ +TARGET = nrf52dk diff --git a/examples/platform-specific/nrf52dk/coap-demo/coap-server.c b/examples/platform-specific/nrf52dk/coap-demo/coap-server/coap-server.c similarity index 95% rename from examples/platform-specific/nrf52dk/coap-demo/coap-server.c rename to examples/platform-specific/nrf52dk/coap-demo/coap-server/coap-server.c index 9df51788617e472a9154088d9939818e194c1cee..6b4025cd3454c0e6f7f62bd3f1c69f095aa0d211 100644 --- a/examples/platform-specific/nrf52dk/coap-demo/coap-server.c +++ b/examples/platform-specific/nrf52dk/coap-demo/coap-server/coap-server.c @@ -51,7 +51,7 @@ #include <string.h> #include "contiki.h" #include "contiki-net.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "uip.h" #include "dev/button-sensor.h" #include "dev/leds.h" @@ -63,7 +63,7 @@ * Resources to be activated need to be imported through the extern keyword. * The build system automatically compiles the resources in the corresponding sub-directory. */ -extern resource_t res_led3; +extern coap_resource_t res_led3; static void print_local_addresses(void) @@ -99,13 +99,13 @@ PROCESS_THREAD(er_example_server, ev, data) PRINTF("uIP buffer: %u\n", UIP_BUFSIZE); PRINTF("LL header: %u\n", UIP_LLH_LEN); PRINTF("IP+UDP header: %u\n", UIP_IPUDPH_LEN); - PRINTF("REST max chunk: %u\n", REST_MAX_CHUNK_SIZE); + PRINTF("REST max chunk: %u\n", COAP_MAX_CHUNK_SIZE); print_local_addresses(); /* Initialize the REST engine. */ - rest_init_engine(); - rest_activate_resource(&res_led3, "lights/led3"); + coap_engine_init(); + coap_activate_resource(&res_led3, "lights/led3"); SENSORS_ACTIVATE(button_1); diff --git a/examples/platform-specific/nrf52dk/coap-demo/resources/res-leds.c b/examples/platform-specific/nrf52dk/coap-demo/resources/res-leds.c index f990fcf3814a75c48355be942b5e9d0f08377681..695eca6a2da565b007b306afc2040f9ab2a83e27 100644 --- a/examples/platform-specific/nrf52dk/coap-demo/resources/res-leds.c +++ b/examples/platform-specific/nrf52dk/coap-demo/resources/res-leds.c @@ -40,22 +40,25 @@ #include <string.h> #include "contiki.h" -#include "rest-engine.h" +#include "coap.h" +#include "coap-engine.h" #include "dev/leds.h" #define DEBUG DEBUG_NONE #include "net/ipv6/uip-debug.h" static void -res_post_put_handler(void *request, void *response, uint8_t *buffer, +res_post_put_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void -res_get_handler(void *request, void *response, uint8_t *buffer, +res_get_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void -res_event_handler(); +res_event_handler(void); /*A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated*/ EVENT_RESOURCE(res_led3, @@ -68,30 +71,30 @@ EVENT_RESOURCE(res_led3, ); static void -res_post_put_handler(void *request, void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +res_post_put_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const uint8_t *payload; - REST.get_request_payload(request, &payload); + coap_get_payload(request, &payload); - if (*payload == '0' || *payload == '1') { - if (*payload == '1') { + if(*payload == '0' || *payload == '1') { + if(*payload == '1') { leds_on(LEDS_3); } else { leds_off(LEDS_3); } - REST.notify_subscribers(&res_led3); - REST.set_response_status(response, REST.status.CHANGED); + coap_notify_observers(&res_led3); + coap_set_status_code(response, CHANGED_2_04); } else { - REST.set_response_status(response, REST.status.BAD_REQUEST); + coap_set_status_code(response, BAD_REQUEST_4_00); } } static void -res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +res_get_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - REST.set_response_payload(response, buffer, snprintf((char *)buffer, preferred_size, "%d", (leds_get() & LEDS_3) ? 1 : 0)); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, buffer, snprintf((char *)buffer, preferred_size, "%d", (leds_get() & LEDS_3) ? 1 : 0)); } /* @@ -102,5 +105,5 @@ static void res_event_handler() { /* Notify the registered observers which will trigger the res_get_handler to create the response. */ - REST.notify_subscribers(&res_led3); + coap_notify_observers(&res_led3); } diff --git a/examples/platform-specific/nrf52dk/mqtt-demo/Makefile b/examples/platform-specific/nrf52dk/mqtt-demo/Makefile index bf1b35fffa661c198e2eec0ee50dff841f8847cd..dc3e23e67d86fb7b9ec89187048fa7bf5d82cbf5 100644 --- a/examples/platform-specific/nrf52dk/mqtt-demo/Makefile +++ b/examples/platform-specific/nrf52dk/mqtt-demo/Makefile @@ -1,6 +1,9 @@ -all: mqtt-demo +CONTIKI_PROJECT = mqtt-demo +all: $(CONTIKI_PROJECT) -MAKE_ROUTING = MAKE_ROUTING_NONE +PLATFORMS_ONLY = nrf52dk + +MAKE_ROUTING = MAKE_ROUTING_NULLROUTING MODULES += os/net/app-layer/mqtt diff --git a/examples/platform-specific/nrf52dk/mqtt-demo/mqtt-demo.c b/examples/platform-specific/nrf52dk/mqtt-demo/mqtt-demo.c index 80339a4adc86d4f490efcaaf1a99fc6260ca0e31..6fa071617f6e82f16a96d8639d9149af12742299 100644 --- a/examples/platform-specific/nrf52dk/mqtt-demo/mqtt-demo.c +++ b/examples/platform-specific/nrf52dk/mqtt-demo/mqtt-demo.c @@ -55,6 +55,7 @@ #include "dev/leds.h" #include <string.h> +#include <strings.h> /*---------------------------------------------------------------------------*/ /* * IBM server: quickstart.messaging.internetofthings.ibmcloud.com diff --git a/examples/platform-specific/nrf52dk/timer-test/Makefile b/examples/platform-specific/nrf52dk/timer-test/Makefile index de851dcf108753781b78a7ef42457f6f3272b3e7..da515a62efc4695480ab35755cbda0c517b4da2f 100644 --- a/examples/platform-specific/nrf52dk/timer-test/Makefile +++ b/examples/platform-specific/nrf52dk/timer-test/Makefile @@ -1,6 +1,8 @@ CONTIKI_PROJECT = timer-test -MAKE_ROUTING = MAKE_ROUTING_NONE +PLATFORMS_ONLY = nrf52dk + +MAKE_ROUTING = MAKE_ROUTING_NULLROUTING MAKE_MAC=MAKE_MAC_NULLMAC NRF52_WITHOUT_SOFTDEVICE=1 diff --git a/examples/platform-specific/zoul/Makefile b/examples/platform-specific/zoul/Makefile index bc018f1717f41be8929eb285d076827f96717e64..88dcb3ce2269031d127887a0a2e40f74e12fe094 100644 --- a/examples/platform-specific/zoul/Makefile +++ b/examples/platform-specific/zoul/Makefile @@ -3,7 +3,7 @@ CONTIKI_PROJECT += test-bmp085-bmp180 test-motion test-rotation-sensor CONTIKI_PROJECT += test-grove-light-sensor test-grove-loudness-sensor CONTIKI_PROJECT += test-weather-meter test-grove-gyro test-lcd test-iaq CONTIKI_PROJECT += test-pm10-sensor test-vac-sensor test-aac-sensor -CONTIKI_PROJECT += test-zonik test-dht22.c test-ac-dimmer.c test-servo.c +CONTIKI_PROJECT += test-zonik test-dht22.c test-ac-dimmer.c CONTIKI_PROJECT += test-bme280 CONTIKI_TARGET_SOURCEFILES += tsl256x.c sht25.c bmpx8x.c motion-sensor.c @@ -15,5 +15,7 @@ MODULES += arch/dev/bme280 all: $(CONTIKI_PROJECT) +PLATFORMS_ONLY = zoul + CONTIKI = ../../.. include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/zoul/at-test/Makefile b/examples/platform-specific/zoul/at-test/Makefile index 8715c949fca1944ebcafa52263e8780cf8922c24..df8ef9da8f25534523b979257bcd22f735bfb1ce 100644 --- a/examples/platform-specific/zoul/at-test/Makefile +++ b/examples/platform-specific/zoul/at-test/Makefile @@ -2,5 +2,7 @@ CONTIKI_PROJECT = at-master-test MODULES = os/services/at-master all: $(CONTIKI_PROJECT) -CONTIKI = ../../.. +PLATFORMS_ONLY = zoul + +CONTIKI = ../../../.. include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/zoul/at-test/at-master-test.c b/examples/platform-specific/zoul/at-test/at-master-test.c index 012010c8700a1d2cad4cab2c157902f54f54a8f3..b7a1acddc4e4f3ed9754787afc7d4aba76fdbe33 100644 --- a/examples/platform-specific/zoul/at-test/at-master-test.c +++ b/examples/platform-specific/zoul/at-test/at-master-test.c @@ -52,6 +52,7 @@ #include "dev/ioc.h" #include "lib/list.h" #include "dev/sha256.h" +#include "net/linkaddr.h" #include <stdio.h> #include <stdint.h> #include <stdlib.h> diff --git a/examples/platform-specific/zoul/orion/README.md b/examples/platform-specific/zoul/orion/README.md index bd57b5284aaa4d4a80466d8d683ec6038d87f84c..d32cc4bcb64f0a114814dff5bccfe078d0b1a8db 100644 --- a/examples/platform-specific/zoul/orion/README.md +++ b/examples/platform-specific/zoul/orion/README.md @@ -25,7 +25,7 @@ To compile and flash run: ```` cd ip64-router -make TARGET=zoul BOARD=router ip64-router.upload +make TARGET=zoul BOARD=orion ip64-router.upload ```` As default we enable the `DHCP` support for autoconfiguration. Just connect to a DHCP-enabled device to obtain an IPv4 IP address and that's it!. diff --git a/examples/platform-specific/zoul/orion/client/Makefile b/examples/platform-specific/zoul/orion/client/Makefile index de6df0e34d97829885b695fa317cafd4770ab770..22354dc98ef8e5048dadf81fb99de6cb068b6782 100644 --- a/examples/platform-specific/zoul/orion/client/Makefile +++ b/examples/platform-specific/zoul/orion/client/Makefile @@ -1,4 +1,4 @@ -CONTIKI_PROJECT = client ifttt_client +CONTIKI_PROJECT = client ifttt-client all: $(CONTIKI_PROJECT) BOARD = orion @@ -7,5 +7,8 @@ MODULES += os/net/app-layer/http-socket WITH_IP64 = 1 +PLATFORMS_ONLY = zoul +BOARDS_ONLY = orion + CONTIKI = ../../../../.. include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/zoul/orion/client/client.c b/examples/platform-specific/zoul/orion/client/client.c index 18f1a5e91c464bae97bf74fa841610a1ff3ae5be..ebbd34fb0f23509fb24a68eed0660993319d0698 100644 --- a/examples/platform-specific/zoul/orion/client/client.c +++ b/examples/platform-specific/zoul/orion/client/client.c @@ -33,7 +33,7 @@ #include "http-socket.h" #include "ipv6/ip64-addr.h" #include "dev/leds.h" -#include "rpl.h" +#include "net/routing/routing.h" #include <stdio.h> /*---------------------------------------------------------------------------*/ static struct http_socket s; diff --git a/examples/platform-specific/zoul/orion/client/ifttt-client.c b/examples/platform-specific/zoul/orion/client/ifttt-client.c index ec1288753d84eeba1ee054cb17618a5ada3ab14f..da2387a851a521587cb17a7117466d288813a500 100644 --- a/examples/platform-specific/zoul/orion/client/ifttt-client.c +++ b/examples/platform-specific/zoul/orion/client/ifttt-client.c @@ -33,8 +33,8 @@ #include "http-socket.h" #include "ipv6/ip64-addr.h" #include "dev/leds.h" -#include "rpl.h" -#include "dev/button-sensor.h" +#include "net/routing/routing.h" +#include "dev/button-hal.h" #include <stdio.h> /*---------------------------------------------------------------------------*/ static struct http_socket s; @@ -138,13 +138,10 @@ PROCESS_THREAD(http_example_process, ev, data) while(1) { PROCESS_YIELD(); - if((ev == sensors_event) && (data == &button_sensor)) { - if(button_sensor.value(BUTTON_SENSOR_VALUE_TYPE_LEVEL) == - BUTTON_SENSOR_PRESSED_LEVEL) { - leds_on(LEDS_GREEN); - printf("Button pressed! sending a POST to IFTTT\n"); - http_socket_post(&s, url_buffer, NULL, 0, NULL, callback, NULL); - } + if(ev == button_hal_release_event) { + leds_on(LEDS_GREEN); + printf("Button pressed! sending a POST to IFTTT\n"); + http_socket_post(&s, url_buffer, NULL, 0, NULL, callback, NULL); } } diff --git a/examples/platform-specific/zoul/orion/client/project-conf.h b/examples/platform-specific/zoul/orion/client/project-conf.h index ca2361f0a393731de06fcb7c434dae0fd56bb830..0bc2443950b5e6f719d3d3d56de4b3d2ea07b8c4 100644 --- a/examples/platform-specific/zoul/orion/client/project-conf.h +++ b/examples/platform-specific/zoul/orion/client/project-conf.h @@ -31,6 +31,10 @@ /*---------------------------------------------------------------------------*/ #ifndef PROJECT_CONF_H_ #define PROJECT_CONF_H_ + +/* Prevent the router from dropping below LPM2 to avoid RAM overflow */ +#define LPM_CONF_MAX_PM 0 + /*---------------------------------------------------------------------------*/ /* Use either the cc1200_driver for sub-1GHz, or cc2538_rf_driver (default) * for 2.4GHz built-in radio interface @@ -40,9 +44,10 @@ /* Alternate between ANTENNA_SW_SELECT_SUBGHZ or ANTENNA_SW_SELECT_2_4GHZ */ #define ANTENNA_SW_SELECT_DEF_CONF ANTENNA_SW_SELECT_2_4GHZ +#define UIP_CONF_TCP 1 #define RESOLV_CONF_SUPPORTS_MDNS 0 #define NETSTCK_ROUTING_STATE_SIZE 3 -#define NBR_TABLE_CONF_MAX_NEIGHBORS 3 +#define NBR_TABLE_CONF_MAX_NEIGHBORS 3 #define HTTP_CLIENT_BUFFER_LEN 256 diff --git a/examples/platform-specific/zoul/orion/ip64-router/Makefile b/examples/platform-specific/zoul/orion/ip64-router/Makefile index 8300617cab575303d0ed568417600cf86503c033..4d532912a3694b413742b6576bdcac978c8981df 100644 --- a/examples/platform-specific/zoul/orion/ip64-router/Makefile +++ b/examples/platform-specific/zoul/orion/ip64-router/Makefile @@ -1,4 +1,5 @@ -all: ip64-router +CONTIKI_PROJECT = ip64-router +all: $(CONTIKI_PROJECT) BOARD = orion @@ -8,4 +9,7 @@ WITH_IP64 = 1 PROJECT_SOURCEFILES += httpd-simple.c +PLATFORMS_ONLY = zoul +BOARDS_ONLY = orion + include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/zoul/orion/ip64-router/Makefile.target b/examples/platform-specific/zoul/orion/ip64-router/Makefile.target index 75430a6e4228757cd766c5497c24bc42c3d57c30..420fc52ccfd45582d4d726f93402fbdf23dfe953 100644 --- a/examples/platform-specific/zoul/orion/ip64-router/Makefile.target +++ b/examples/platform-specific/zoul/orion/ip64-router/Makefile.target @@ -1 +1,2 @@ TARGET = zoul +BOARD = orion diff --git a/examples/platform-specific/zoul/orion/ip64-router/ip64-router.c b/examples/platform-specific/zoul/orion/ip64-router/ip64-router.c index 433f58426a21e0226edb36db2336fb67edd4dc74..5f2a98e24e41060f1f83d263e1f7f45c418515cb 100644 --- a/examples/platform-specific/zoul/orion/ip64-router/ip64-router.c +++ b/examples/platform-specific/zoul/orion/ip64-router/ip64-router.c @@ -45,8 +45,7 @@ #include "contiki-net.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" -#include "rpl.h" -#include "rpl-dag-root.h" +#include "net/routing/routing.h" #include "dev/leds.h" #include "ip64/ip64.h" #include "net/netstack.h" @@ -248,7 +247,7 @@ PT_THREAD(generate_routes(struct httpd_state *s)) #if WEBSERVER_CONF_LOADTIME numticks = clock_time() - numticks + 1; - ADD(" <i>(%u.%02u sec)</i>", numticks / CLOCK_SECOND, + ADD(" <i>(%u.%02u sec)</i>", numticks / CLOCK_SECOND, (100 * (numticks % CLOCK_SECOND)) / CLOCK_SECOND)); #endif @@ -308,7 +307,7 @@ PROCESS_THREAD(router_node_process, ev, data) leds_off(LEDS_DHCP); /* Set us up as a RPL root node. */ - rpl_dag_root_init_dag_delay(); + NETSTACK_ROUTING.root_start(); /* ... and do nothing more. */ while(1) { diff --git a/examples/platform-specific/zoul/rev-b/Makefile b/examples/platform-specific/zoul/rev-b/Makefile index 61d9cf43285dcf94e52d2250dd7c6eb22ca76d9a..43d381c3fa707364964cb90f29113242cb2984a6 100644 --- a/examples/platform-specific/zoul/rev-b/Makefile +++ b/examples/platform-specific/zoul/rev-b/Makefile @@ -4,5 +4,8 @@ BOARD ?= remote-revb all: $(CONTIKI_PROJECT) +PLATFORMS_ONLY = zoul +BOARDS_ONLY = remote-revb + CONTIKI = ../../../.. include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/zoul/rev-b/Makefile.target b/examples/platform-specific/zoul/rev-b/Makefile.target index 75430a6e4228757cd766c5497c24bc42c3d57c30..cb458a6d91f85b7bd08b2c2ba09ac5a65c180a28 100644 --- a/examples/platform-specific/zoul/rev-b/Makefile.target +++ b/examples/platform-specific/zoul/rev-b/Makefile.target @@ -1 +1,2 @@ TARGET = zoul +BOARD = remote-revb diff --git a/examples/platform-specific/zoul/rev-b/test-power-mgmt.c b/examples/platform-specific/zoul/rev-b/test-power-mgmt.c index 0bb364aba737bdd82da9b9bb2c394f59fe305ef3..942a01933d75c932dead2e2e5c1d89123f688f52 100644 --- a/examples/platform-specific/zoul/rev-b/test-power-mgmt.c +++ b/examples/platform-specific/zoul/rev-b/test-power-mgmt.c @@ -136,7 +136,7 @@ PROCESS_THREAD(test_remote_pm, ev, data) printf("PM: Soft shutdown, timeout set to %lu\n", pm_get_timeout()); leds_off(LEDS_ALL); - leds_on(LEDS_PURPLE); + leds_on(LEDS_RED); /* Wait just enough to be able to check the LED result */ etimer_set(&et, CLOCK_SECOND * 3); diff --git a/examples/platform-specific/zoul/rtcc/Makefile b/examples/platform-specific/zoul/rtcc/Makefile index 9aca10bbc6358a43aa3f053dddfbf97cccb15dfa..9a3bc0aecba4451475085c1de3efac06c94f003b 100644 --- a/examples/platform-specific/zoul/rtcc/Makefile +++ b/examples/platform-specific/zoul/rtcc/Makefile @@ -4,5 +4,9 @@ TARGET = zoul all: $(CONTIKI_PROJECT) +PLATFORMS_ONLY = zoul +# Only the Re-Mote is equiped with an RTCC +BOARDS_ONLY = remote-reva remote-revb + CONTIKI = ../../../.. include $(CONTIKI)/Makefile.include diff --git a/examples/platform-specific/zoul/test-grove-gyro.c b/examples/platform-specific/zoul/test-grove-gyro.c index 978aa69f8e472c9328c6edb4a1bce28bc3a64075..74ff66e0338c9165df853ebabd686569204d1023 100644 --- a/examples/platform-specific/zoul/test-grove-gyro.c +++ b/examples/platform-specific/zoul/test-grove-gyro.c @@ -65,7 +65,7 @@ gyro_interrupt_callback(uint8_t status) * returns the outcome of the read operation, check to validate if the * data is valid to read */ - leds_toggle(LEDS_PURPLE); + leds_toggle(LEDS_RED); printf("Gyro: X_axis %u, Y_axis %u, Z_axis %u\n", gyro_values.x, gyro_values.y, diff --git a/examples/platform-specific/zoul/test-lcd.c b/examples/platform-specific/zoul/test-lcd.c index 6a17df99c7d31ec3a286d3309bb1100d1673269e..9b30ab25aa04f77ba462d3e9dc7d745fa9d511b2 100644 --- a/examples/platform-specific/zoul/test-lcd.c +++ b/examples/platform-specific/zoul/test-lcd.c @@ -47,7 +47,7 @@ #include <stdio.h> #include "contiki.h" #include "dev/rgb-bl-lcd.h" -#include "dev/button-sensor.h" +#include "dev/button-hal.h" /*---------------------------------------------------------------------------*/ #define SCROLL_PERIOD (CLOCK_SECOND / 6) /*---------------------------------------------------------------------------*/ @@ -104,18 +104,13 @@ PROCESS_THREAD(remote_lcd_process, ev, data) printf("Counter: %05u\n", counter); counter++; etimer_restart(&et); - } else if(ev == sensors_event) { - if(data == &button_sensor) { - if(button_sensor.value(BUTTON_SENSOR_VALUE_TYPE_LEVEL) == - BUTTON_SENSOR_PRESSED_LEVEL) { - printf("Button pressed!!\n"); - lcd_set_cursor(0, LCD_RGB_1ST_ROW); - lcd_write("Button pressed!!"); - } else { - lcd_set_cursor(0, LCD_RGB_1ST_ROW); - lcd_write("Press the button!"); - } - } + } else if(ev == button_hal_press_event) { + printf("Button pressed!!\n"); + lcd_set_cursor(0, LCD_RGB_1ST_ROW); + lcd_write("Button pressed!!"); + } else if(ev == button_hal_release_event) { + lcd_set_cursor(0, LCD_RGB_1ST_ROW); + lcd_write("Press the button!"); } } diff --git a/examples/platform-specific/zoul/test-tsl256x.c b/examples/platform-specific/zoul/test-tsl256x.c index ed6f72327eed58df49768c8a1b18edded40e6321..0e6fce5882e3d4e33fc8f32ec4eb0d652e710313 100644 --- a/examples/platform-specific/zoul/test-tsl256x.c +++ b/examples/platform-specific/zoul/test-tsl256x.c @@ -63,7 +63,7 @@ void light_interrupt_callback(uint8_t value) { printf("* Light sensor interrupt!\n"); - leds_toggle(LEDS_PURPLE); + leds_toggle(LEDS_RED); } /*---------------------------------------------------------------------------*/ PROCESS_THREAD(remote_tsl256x_process, ev, data) diff --git a/examples/rpl-border-router/Makefile b/examples/rpl-border-router/Makefile index 76c07cb8b1e95d1bbdf89b05193926f1c73337dd..4d2db2a8525bf1ee516d195d87bb7e1e11d73e09 100644 --- a/examples/rpl-border-router/Makefile +++ b/examples/rpl-border-router/Makefile @@ -1,21 +1,16 @@ -PROJECTDIRS += common -PREFIX ?= fd00::1/64 +CONTIKI_PROJECT = border-router +all: $(CONTIKI_PROJECT) CONTIKI = ../.. --include $(CONTIKI)/Makefile.identify-target +# The BR is either native or embedded, and in the latter case must support SLIP +PLATFORMS_EXCLUDE = nrf52dk -all: border-router.$(TARGET) - -ifeq ($(TARGET),native) - SOURCES_DIR = native -else - SOURCES_DIR = embedded -endif - -include $(SOURCES_DIR)/Makefile - -PROJECTDIRS += $(SOURCES_DIR) -PROJECT_SOURCEFILES += httpd-simple.c webserver.c border-router-common.c -CFLAGS += -DPROJECT_CONF_PATH=\"$(SOURCES_DIR)/project-conf.h\" +# Include RPL BR module +MODULES += os/services/rpl-border-router +# Include webserver module +MODULES_REL += webserver +# Include optional target-specific module +include $(CONTIKI)/Makefile.identify-target +MODULES_REL += $(TARGET) include $(CONTIKI)/Makefile.include diff --git a/examples/rpl-border-router/border-router.c b/examples/rpl-border-router/border-router.c index 30b6d615083cdff4e3ad9d250e5f4d1934920410..416d18093d564c09d3ff76e25de402f112aaf98b 100644 --- a/examples/rpl-border-router/border-router.c +++ b/examples/rpl-border-router/border-router.c @@ -32,11 +32,26 @@ #include "contiki.h" -PROCESS_NAME(border_router_process); +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "RPL BR" +#define LOG_LEVEL LOG_LEVEL_INFO + +/* Declare and auto-start this file's process */ +PROCESS(contiki_ng_br, "Contiki-NG Border Router"); +AUTOSTART_PROCESSES(&contiki_ng_br); + +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(contiki_ng_br, ev, data) +{ + PROCESS_BEGIN(); #if BORDER_ROUTER_CONF_WEBSERVER -PROCESS_NAME(webserver_nogui_process); -AUTOSTART_PROCESSES(&border_router_process, &webserver_nogui_process); -#else /* BORDER_ROUTER_CONF_WEBSERVER */ -AUTOSTART_PROCESSES(&border_router_process); + PROCESS_NAME(webserver_nogui_process); + process_start(&webserver_nogui_process, NULL); #endif /* BORDER_ROUTER_CONF_WEBSERVER */ + + LOG_INFO("Contiki-NG Border Router started\n"); + + PROCESS_END(); +} diff --git a/examples/rpl-border-router/common/webserver.c b/examples/rpl-border-router/common/webserver.c deleted file mode 100644 index 00adddb7ce5908ec7ee6735e96bca99efa24abe0..0000000000000000000000000000000000000000 --- a/examples/rpl-border-router/common/webserver.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (c) 2017, RISE SICS - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ - -#include "contiki.h" -#include "rpl.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ - -#include <stdio.h> -#include <string.h> - -/*---------------------------------------------------------------------------*/ -static const char *TOP = "<html><head><title>Contiki-NG</title></head><body>\n"; -static const char *BOTTOM = "</body></html>\n"; -#if BUF_USES_STACK -static char *bufptr, *bufend; -#define ADD(...) do { \ - bufptr += snprintf(bufptr, bufend - bufptr, __VA_ARGS__); \ - } while(0) -#else -static char buf[256]; -static int blen; -#define ADD(...) do { \ - blen += snprintf(&buf[blen], sizeof(buf) - blen, __VA_ARGS__); \ - } while(0) -#endif - -/* Use simple webserver with only one page for minimum footprint. - * Multiple connections can result in interleaved tcp segments since - * a single static buffer is used for all segments. - */ -#include "httpd-simple.h" -/* The internal webserver can provide additional information if - * enough program flash is available. - */ -#define WEBSERVER_CONF_LOADTIME 0 -#define WEBSERVER_CONF_FILESTATS 0 -#define WEBSERVER_CONF_NEIGHBOR_STATUS 0 -/* Adding links requires a larger RAM buffer. To avoid static allocation - * the stack can be used for formatting; however tcp retransmissions - * and multiple connections can result in garbled segments. - * TODO:use PSOCk_GENERATOR_SEND and tcp state storage to fix this. - */ -#define WEBSERVER_CONF_ROUTE_LINKS 0 -#if WEBSERVER_CONF_ROUTE_LINKS -#define BUF_USES_STACK 1 -#endif - -/*---------------------------------------------------------------------------*/ -static void -ipaddr_add(const uip_ipaddr_t *addr) -{ - uint16_t a; - int i, f; - for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { - a = (addr->u8[i] << 8) + addr->u8[i + 1]; - if(a == 0 && f >= 0) { - if(f++ == 0) { - ADD("::"); - } - } else { - if(f > 0) { - f = -1; - } else if(i > 0) { - ADD(":"); - } - ADD("%x", a); - } - } -} -/*---------------------------------------------------------------------------*/ -static -PT_THREAD(generate_routes(struct httpd_state *s)) -{ - static uip_ds6_route_t *r; -#if RPL_WITH_NON_STORING - static rpl_ns_node_t *link; -#endif /* RPL_WITH_NON_STORING */ - static uip_ds6_nbr_t *nbr; -#if BUF_USES_STACK - char buf[256]; -#endif -#if WEBSERVER_CONF_LOADTIME - static clock_time_t numticks; - numticks = clock_time(); -#endif - - PSOCK_BEGIN(&s->sout); - - SEND_STRING(&s->sout, TOP); -#if BUF_USES_STACK - bufptr = buf; - bufend = bufptr + sizeof(buf); -#else - blen = 0; -#endif - ADD("Neighbors<pre>"); - - for(nbr = nbr_table_head(ds6_neighbors); - nbr != NULL; - nbr = nbr_table_next(ds6_neighbors, nbr)) { - -#if WEBSERVER_CONF_NEIGHBOR_STATUS -#if BUF_USES_STACK - { char *j = bufptr + 25; - ipaddr_add(&nbr->ipaddr); - while(bufptr < j) ADD(" "); - switch(nbr->state) { - case NBR_INCOMPLETE: ADD(" INCOMPLETE"); - break; - case NBR_REACHABLE: ADD(" REACHABLE"); - break; - case NBR_STALE: ADD(" STALE"); - break; - case NBR_DELAY: ADD(" DELAY"); - break; - case NBR_PROBE: ADD(" NBR_PROBE"); - break; - } - } -#else - { uint8_t j = blen + 25; - ipaddr_add(&nbr->ipaddr); - while(blen < j) ADD(" "); - switch(nbr->state) { - case NBR_INCOMPLETE: ADD(" INCOMPLETE"); - break; - case NBR_REACHABLE: ADD(" REACHABLE"); - break; - case NBR_STALE: ADD(" STALE"); - break; - case NBR_DELAY: ADD(" DELAY"); - break; - case NBR_PROBE: ADD(" NBR_PROBE"); - break; - } - } -#endif -#else - ipaddr_add(&nbr->ipaddr); -#endif - - ADD("\n"); -#if BUF_USES_STACK - if(bufptr > bufend - 45) { - SEND_STRING(&s->sout, buf); - bufptr = buf; - bufend = bufptr + sizeof(buf); - } -#else - if(blen > sizeof(buf) - 45) { - SEND_STRING(&s->sout, buf); - blen = 0; - } -#endif - } - ADD("</pre>Routes<pre>\n"); - SEND_STRING(&s->sout, buf); -#if BUF_USES_STACK - bufptr = buf; - bufend = bufptr + sizeof(buf); -#else - blen = 0; -#endif - - for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { - -#if BUF_USES_STACK -#if WEBSERVER_CONF_ROUTE_LINKS - ADD("<a href=http://["); - ipaddr_add(&r->ipaddr); - ADD("]/status.shtml>"); - ipaddr_add(&r->ipaddr); - ADD("</a>"); -#else - ipaddr_add(&r->ipaddr); -#endif -#else -#if WEBSERVER_CONF_ROUTE_LINKS - ADD("<a href=http://["); - ipaddr_add(&r->ipaddr); - ADD("]/status.shtml>"); - SEND_STRING(&s->sout, buf); - blen = 0; - ipaddr_add(&r->ipaddr); - ADD("</a>"); -#else - ipaddr_add(&r->ipaddr); -#endif -#endif - ADD("/%u (via ", r->length); - ipaddr_add(uip_ds6_route_nexthop(r)); - if(1 || (r->state.lifetime < 600)) { - ADD(") %lus\n", (unsigned long)r->state.lifetime); - } else { - ADD(")\n"); - } - SEND_STRING(&s->sout, buf); -#if BUF_USES_STACK - bufptr = buf; - bufend = bufptr + sizeof(buf); -#else - blen = 0; -#endif - } - ADD("</pre>"); - -#if RPL_WITH_NON_STORING - ADD("Links<pre>\n"); - SEND_STRING(&s->sout, buf); -#if BUF_USES_STACK - bufptr = buf; - bufend = bufptr + sizeof(buf); -#else - blen = 0; -#endif - for(link = rpl_ns_node_head(); link != NULL; link = rpl_ns_node_next(link)) { - if(link->parent != NULL) { - uip_ipaddr_t child_ipaddr; - uip_ipaddr_t parent_ipaddr; - - rpl_ns_get_node_global_addr(&child_ipaddr, link); - rpl_ns_get_node_global_addr(&parent_ipaddr, link->parent); - -#if BUF_USES_STACK -#if WEBSERVER_CONF_ROUTE_LINKS - ADD("<a href=http://["); - ipaddr_add(&child_ipaddr); - ADD("]/status.shtml>"); - ipaddr_add(&child_ipaddr); - ADD("</a>"); -#else - ipaddr_add(&child_ipaddr); -#endif -#else -#if WEBSERVER_CONF_ROUTE_LINKS - ADD("<a href=http://["); - ipaddr_add(&child_ipaddr); - ADD("]/status.shtml>"); - SEND_STRING(&s->sout, buf); - blen = 0; - ipaddr_add(&child_ipaddr); - ADD("</a>"); -#else - ipaddr_add(&child_ipaddr); -#endif -#endif - - ADD(" (parent: "); - ipaddr_add(&parent_ipaddr); - if(1 || (link->lifetime < 600)) { - ADD(") %us\n", (unsigned int)link->lifetime); - } else { - ADD(")\n"); - } - SEND_STRING(&s->sout, buf); -#if BUF_USES_STACK - bufptr = buf; - bufend = bufptr + sizeof(buf); -#else - blen = 0; -#endif - } - } - ADD("</pre>"); -#endif /* RPL_WITH_NON_STORING */ - -#if WEBSERVER_CONF_FILESTATS - static uint16_t numtimes; - ADD("<br><i>This page sent %u times</i>", ++numtimes); -#endif - -#if WEBSERVER_CONF_LOADTIME - numticks = clock_time() - numticks + 1; - ADD(" <i>(%u.%02u sec)</i>", numticks / CLOCK_SECOND, (100 * (numticks % CLOCK_SECOND)) / CLOCK_SECOND)); -#endif - - SEND_STRING(&s->sout, buf); - SEND_STRING(&s->sout, BOTTOM); - - PSOCK_END(&s->sout); -} -#if BORDER_ROUTER_CONF_WEBSERVER -/*---------------------------------------------------------------------------*/ -PROCESS(webserver_nogui_process, "Web server"); -PROCESS_THREAD(webserver_nogui_process, ev, data) -{ - PROCESS_BEGIN(); - - httpd_init(); - - while(1) { - PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event); - httpd_appcall(data); - } - - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ -httpd_simple_script_t -httpd_simple_get_script(const char *name) -{ - return generate_routes; -} -#endif /* BORDER_ROUTER_CONF_WEBSERVER */ diff --git a/examples/rpl-border-router/embedded/Makefile b/examples/rpl-border-router/embedded/Makefile deleted file mode 100644 index 5faba70c8cb881ab32a680ff57c841a751e116e3..0000000000000000000000000000000000000000 --- a/examples/rpl-border-router/embedded/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -### Optionally, the target can add its own Makefile, to do things like e.g. -### add more source files to the build or define make variables. --include $(SOURCES_DIR)/$(TARGET)/Makefile.$(TARGET) - -PROJECTDIRS += $(SOURCES_DIR)/$(TARGET) - -PROJECT_SOURCEFILES += slip-bridge.c border-router-embedded.c - -$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c - (cd $(CONTIKI)/tools && $(MAKE) tunslip6) - -connect-router: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 $(PREFIX) - -connect-router-cooja: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 $(PREFIX) diff --git a/examples/rpl-border-router/embedded/sky/Makefile.sky b/examples/rpl-border-router/embedded/sky/Makefile.sky deleted file mode 100644 index c3d097481e048de9f0dc7efa3c0c1bb06bfe2d67..0000000000000000000000000000000000000000 --- a/examples/rpl-border-router/embedded/sky/Makefile.sky +++ /dev/null @@ -1,3 +0,0 @@ -PROJECT_SOURCEFILES += slip-bridge-putchar.c - -CFLAGS += -DTARGET_CONF_PATH=\"target-conf.h\" diff --git a/examples/rpl-border-router/embedded/sky/slip-bridge-putchar.c b/examples/rpl-border-router/embedded/sky/slip-bridge-putchar.c deleted file mode 100644 index f7f501ba1951b610dbbff90f93422b1e4a35c4ab..0000000000000000000000000000000000000000 --- a/examples/rpl-border-router/embedded/sky/slip-bridge-putchar.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ -/*---------------------------------------------------------------------------*/ -#include "contiki.h" -#include "dev/slip.h" - -#include <string.h> -/*---------------------------------------------------------------------------*/ -#define SLIP_END 0300 -#undef putchar -/*---------------------------------------------------------------------------*/ -int -putchar(int c) -{ - static char debug_frame = 0; - - if(!debug_frame) { /* Start of debug output */ - slip_arch_writeb(SLIP_END); - slip_arch_writeb('\r'); /* Type debug line == '\r' */ - debug_frame = 1; - } - - /* Need to also print '\n' because for example COOJA will not show - any output before line end */ - slip_arch_writeb((char)c); - - /* - * Line buffered output, a newline marks the end of debug output and - * implicitly flushes debug output. - */ - if(c == '\n') { - slip_arch_writeb(SLIP_END); - debug_frame = 0; - } - return c; -} -/*---------------------------------------------------------------------------*/ diff --git a/examples/rpl-border-router/native/Makefile b/examples/rpl-border-router/native/Makefile deleted file mode 100644 index 30690df0f38c23e37f8c381bf63e4ba1bd3ff8b9..0000000000000000000000000000000000000000 --- a/examples/rpl-border-router/native/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -MODULES += os/services/slip-cmd - -PROJECT_SOURCEFILES += border-router-native.c -PROJECT_SOURCEFILES += border-router-cmds.c tun-bridge.c -PROJECT_SOURCEFILES += slip-config.c slip-dev.c border-router-mac.c - -MAKE_MAC = MAKE_MAC_OTHER -MAKE_NET = MAKE_NET_IPV6 - -connect-router: border-router.native - sudo ./border-router.native fd00::1/64 diff --git a/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/project-conf.h b/examples/rpl-border-router/project-conf.h similarity index 80% rename from examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/project-conf.h rename to examples/rpl-border-router/project-conf.h index c34c364e3714b824932de8ac9ae3e7f9b6f690d6..a2ffcc9500164a78fc75556d5fce4c85bd5ea09e 100644 --- a/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/project-conf.h +++ b/examples/rpl-border-router/project-conf.h @@ -28,21 +28,19 @@ * */ -#ifndef BR_PROJECT_ROUTER_CONF_H_ -#define BR_PROJECT_ROUTER_CONF_H_ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ -#ifndef UIP_FALLBACK_INTERFACE -#define UIP_FALLBACK_INTERFACE rpl_interface +#ifndef WEBSERVER_CONF_CFS_CONNS +#define WEBSERVER_CONF_CFS_CONNS 2 #endif -/* Needed for slip-bridge */ -#define SLIP_BRIDGE_CONF_NO_PUTCHAR 0 - -#define UIP_CONF_TCP 0 -#define QUEUEBUF_CONF_NUM 16 - -#define TSCH_QUEUE_CONF_MAX_NEIGHBOR_QUEUES 8 +#ifndef BORDER_ROUTER_CONF_WEBSERVER +#define BORDER_ROUTER_CONF_WEBSERVER 1 +#endif -#include "../../common-conf.h" +#if BORDER_ROUTER_CONF_WEBSERVER +#define UIP_CONF_TCP 1 +#endif -#endif /* PROJECT_ROUTER_CONF_H_ */ +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/rpl-border-router/sky/module-macros.h b/examples/rpl-border-router/sky/module-macros.h new file mode 100644 index 0000000000000000000000000000000000000000..f9c7b408c1c765f5f9c4e2f559f589972f1e505e --- /dev/null +++ b/examples/rpl-border-router/sky/module-macros.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/* Save some RAM and ROM */ +#define QUEUEBUF_CONF_NUM 4 +#define UIP_CONF_BUFFER_SIZE 140 +#define BORDER_ROUTER_CONF_WEBSERVER 0 +/*---------------------------------------------------------------------------*/ diff --git a/examples/rpl-border-router/common/httpd-simple.c b/examples/rpl-border-router/webserver/httpd-simple.c similarity index 99% rename from examples/rpl-border-router/common/httpd-simple.c rename to examples/rpl-border-router/webserver/httpd-simple.c index dbe1ac80f1a4ebb119bd47de0163ba05473b8fd7..d8ce76816f47c4076bcd154606e02824d09dffdd 100644 --- a/examples/rpl-border-router/common/httpd-simple.c +++ b/examples/rpl-border-router/webserver/httpd-simple.c @@ -37,14 +37,11 @@ * Joakim Eriksson <joakime@sics.se> */ -#include <stdio.h> -#include <string.h> - +#include "contiki.h" #include "contiki-net.h" -#if UIP_CONF_TCP == 0 -#error HTTP server needs TCP enabled -#endif +#include <stdio.h> +#include <string.h> #include "httpd-simple.h" #define webserver_log_file(...) diff --git a/examples/rpl-border-router/common/httpd-simple.h b/examples/rpl-border-router/webserver/httpd-simple.h similarity index 100% rename from examples/rpl-border-router/common/httpd-simple.h rename to examples/rpl-border-router/webserver/httpd-simple.h diff --git a/examples/rpl-border-router/webserver/webserver.c b/examples/rpl-border-router/webserver/webserver.c new file mode 100644 index 0000000000000000000000000000000000000000..3658381bfc40ca22766cf5c6d5bc9c5844309f37 --- /dev/null +++ b/examples/rpl-border-router/webserver/webserver.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2017, RISE SICS + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#include "contiki.h" +#include "net/routing/routing.h" +#include "net/ipv6/uip-ds6-route.h" +#include "net/ipv6/uip-sr.h" + +#include <stdio.h> +#include <string.h> + +/*---------------------------------------------------------------------------*/ +static const char *TOP = "<html>\n <head>\n <title>Contiki-NG</title>\n </head>\n<body>\n"; +static const char *BOTTOM = "\n</body>\n</html>\n"; +static char buf[256]; +static int blen; +#define ADD(...) do { \ + blen += snprintf(&buf[blen], sizeof(buf) - blen, __VA_ARGS__); \ + } while(0) +#define SEND(s) do { \ + SEND_STRING(s, buf); \ + blen = 0; \ +} while(0); + +/* Use simple webserver with only one page for minimum footprint. + * Multiple connections can result in interleaved tcp segments since + * a single static buffer is used for all segments. + */ +#include "httpd-simple.h" + +/*---------------------------------------------------------------------------*/ +static void +ipaddr_add(const uip_ipaddr_t *addr) +{ + uint16_t a; + int i, f; + for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { + a = (addr->u8[i] << 8) + addr->u8[i + 1]; + if(a == 0 && f >= 0) { + if(f++ == 0) { + ADD("::"); + } + } else { + if(f > 0) { + f = -1; + } else if(i > 0) { + ADD(":"); + } + ADD("%x", a); + } + } +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(generate_routes(struct httpd_state *s)) +{ + static uip_ds6_nbr_t *nbr; + + PSOCK_BEGIN(&s->sout); + SEND_STRING(&s->sout, TOP); + + ADD(" Neighbors\n <ul>\n"); + SEND(&s->sout); + for(nbr = nbr_table_head(ds6_neighbors); + nbr != NULL; + nbr = nbr_table_next(ds6_neighbors, nbr)) { + ADD(" <li>"); + ipaddr_add(&nbr->ipaddr); + ADD("</li>\n"); + SEND(&s->sout); + } + ADD(" </ul>\n"); + SEND(&s->sout); + +#if (UIP_MAX_ROUTES != 0) + { + static uip_ds6_route_t *r; + ADD(" Routes\n <ul>\n"); + SEND(&s->sout); + for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { + ADD(" <li>"); + ipaddr_add(&r->ipaddr); + ADD("/%u (via ", r->length); + ipaddr_add(uip_ds6_route_nexthop(r)); + ADD(") %lus", (unsigned long)r->state.lifetime); + ADD("</li>\n"); + SEND(&s->sout); + } + ADD(" </ul>\n"); + SEND(&s->sout); + } +#endif /* UIP_MAX_ROUTES != 0 */ + +#if (UIP_SR_LINK_NUM != 0) + if(uip_sr_num_nodes() > 0) { + static uip_sr_node_t *link; + ADD(" Routing links\n <ul>\n"); + SEND(&s->sout); + for(link = uip_sr_node_head(); link != NULL; link = uip_sr_node_next(link)) { + if(link->parent != NULL) { + uip_ipaddr_t child_ipaddr; + uip_ipaddr_t parent_ipaddr; + + NETSTACK_ROUTING.get_sr_node_ipaddr(&child_ipaddr, link); + NETSTACK_ROUTING.get_sr_node_ipaddr(&parent_ipaddr, link->parent); + + ADD(" <li>"); + ipaddr_add(&child_ipaddr); + + ADD(" (parent: "); + ipaddr_add(&parent_ipaddr); + ADD(") %us", (unsigned int)link->lifetime); + + ADD("</li>\n"); + SEND(&s->sout); + } + } + ADD(" </ul>"); + SEND(&s->sout); + } +#endif /* UIP_SR_LINK_NUM != 0 */ + + SEND_STRING(&s->sout, BOTTOM); + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +PROCESS(webserver_nogui_process, "Web server"); +PROCESS_THREAD(webserver_nogui_process, ev, data) +{ + PROCESS_BEGIN(); + + httpd_init(); + + while(1) { + PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event); + httpd_appcall(data); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +httpd_simple_script_t +httpd_simple_get_script(const char *name) +{ + return generate_routes; +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/rpl-udp/Makefile b/examples/rpl-udp/Makefile index e032218062b458fc46196331ad109fc3af3c85ec..26190e839c1c6152af677cf052b7d37330c7eb99 100644 --- a/examples/rpl-udp/Makefile +++ b/examples/rpl-udp/Makefile @@ -1,4 +1,20 @@ -all: udp-client udp-server +CONTIKI_PROJECT = udp-client udp-server +all: $(CONTIKI_PROJECT) + +.PHONY: renode +renode: all +ifneq ($(TARGET),cc2538dk) + $(error Only the cc2538dk TARGET is supported for Renode demo scripts) +endif +ifndef SCRIPT + $(warning SCRIPT not defined! Using "rpl-udp.resc" as default) + renode rpl-udp.resc +else +ifeq ($(wildcard $(SCRIPT)),) + $(error SCRIPT "$(SCRIPT)" does not exist!) +endif + renode $(SCRIPT) +endif CONTIKI=../.. include $(CONTIKI)/Makefile.include diff --git a/examples/rpl-udp/README.md b/examples/rpl-udp/README.md index 2d944360fb106b23980fa84afec155d3463ab85c..baabcdc930b35a518934e082a91a341fc6ad86fe 100644 --- a/examples/rpl-udp/README.md +++ b/examples/rpl-udp/README.md @@ -9,3 +9,9 @@ back to the originator. The `.csc` files show example networks in the Cooja simulator, for sky motes and for cooja motes. + +For this example a "renode" make target is available, to run a two node +emulation in the Renode framework. For further instructions on installing and +using Renode please refer to [Contiki-NG wiki][1]. + +[1]: https://github.com/contiki-ng/contiki-ng/wiki/Tutorial:-Running-Contiki%E2%80%90NG-in-Renode diff --git a/examples/rpl-udp/cc2538-node.resc b/examples/rpl-udp/cc2538-node.resc new file mode 100644 index 0000000000000000000000000000000000000000..8d5b943291a9b37ddaac501ed9c82c9f135f2c8a --- /dev/null +++ b/examples/rpl-udp/cc2538-node.resc @@ -0,0 +1,30 @@ +mach create $name +using sysbus +machine LoadPlatformDescription @platforms/cpus/cc2538.repl +machine SetClockSource sysbus.cpu +machine SetSyncDomainFromEmulation $domain +connector Connect radio wireless + +machine PyDevFromFile @scripts/pydev/rolling-bit.py 0x400D2004 0x4 True "sysctrl" + +$id = `next_value 1` + +macro reset +""" + #set node address. 0x00 0x12 0x4B is TI OUI + sysbus WriteByte 0x00280028 $id + sysbus WriteByte 0x0028002C 0x00 + sysbus WriteByte 0x00280030 0xAB + sysbus WriteByte 0x00280034 0x89 + sysbus WriteByte 0x00280038 0x00 + sysbus WriteByte 0x0028003C 0x4B + sysbus WriteByte 0x00280040 0x12 + sysbus WriteByte 0x00280044 0x00 + + sysbus LoadBinary @http://antmicro.com/projects/renode/cc2538_rom_dump.bin-s_524288-0c196cdc21b5397f82e0ff42b206d1cc4b6d7522 0x0 + sysbus LoadELF $bin + + cpu VectorTableOffset `sysbus GetSymbolAddress "vectors"` +""" + +runMacro $reset diff --git a/examples/rpl-udp/rpl-udp-cooja.csc b/examples/rpl-udp/rpl-udp-cooja.csc index b37169090db51875aef94d27cd47e37d775bb209..a17dd6f453b80fe7777198f2f0c766f2c19ffcd5 100644 --- a/examples/rpl-udp/rpl-udp-cooja.csc +++ b/examples/rpl-udp/rpl-udp-cooja.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>RPL-UDP Example</title> diff --git a/examples/rpl-udp/rpl-udp-sky.csc b/examples/rpl-udp/rpl-udp-sky.csc index f2a217a7b9ffd54b861dccb50b6f2431ebf9f79a..7975acf054271bb0241491434fc75281bc6ac6c7 100644 --- a/examples/rpl-udp/rpl-udp-sky.csc +++ b/examples/rpl-udp/rpl-udp-sky.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>RPL-UDP Example</title> diff --git a/examples/rpl-udp/rpl-udp.resc b/examples/rpl-udp/rpl-udp.resc new file mode 100644 index 0000000000000000000000000000000000000000..8286105495b6bde10690043997567b84594855a0 --- /dev/null +++ b/examples/rpl-udp/rpl-udp.resc @@ -0,0 +1,45 @@ +:name: cc2538 range medium 2 nodes + +###################################################################### +# +# Sample script creating 1 server node and 1 client node using a +# range-based medium function - transmission is possible if nodes are +# in range. Nodes are positioned in a 3D space (x,y,z), +# at a distance of 10 (units) from each other (on the X axis). +# +# Differences in SyncUnit values in machines represent the differences +# in their relative speed. This prevents the machines from +# synchronizing in 100%, which is crucial for Contiki network stack +# stability. +# +###################################################################### + +path add $CWD +emulation CreateWirelessMedium "wireless" +$domain = `emulation AddSyncDomain` +wireless SetSyncDomainFromEmulation $domain + +# The radio is using a range-based medium (with the `Range` set to `11`) +# If not set, the default SimpleMediumFunction will be used (where range is not relevant) +wireless SetRangeWirelessFunction 11 + +######################### UDP SERVER - begin ######################### +$bin=@udp-server.cc2538dk +$name="server" +i $ORIGIN/cc2538-node.resc +wireless SetPosition radio 0 0 0 +machine SyncUnit 100 +showAnalyzer sysbus.uart0 +mach clear +########################## UDP SERVER - end ########################## + +######################### UDP CLIENT - begin ######################### +$bin=@udp-client.cc2538dk +$name="client" + +i $ORIGIN/cc2538-node.resc +wireless SetPosition radio 10 0 0 +machine SyncUnit 110 +showAnalyzer sysbus.uart0 +mach clear +########################## UDP CLIENT - end ########################## diff --git a/examples/rpl-udp/udp-client.c b/examples/rpl-udp/udp-client.c index d59b2b0292ec6b3ea628fcf68caa9f2eace253b5..a10d188ac0ad191b718eeedc04a7502c30a3ed4e 100644 --- a/examples/rpl-udp/udp-client.c +++ b/examples/rpl-udp/udp-client.c @@ -1,5 +1,5 @@ #include "contiki.h" -#include "rpl.h" +#include "net/routing/routing.h" #include "random.h" #include "net/netstack.h" #include "net/ipv6/simple-udp.h" @@ -33,7 +33,10 @@ udp_rx_callback(struct simple_udp_connection *c, uint16_t datalen) { unsigned count = *(unsigned *)data; - LOG_INFO("Received response %u from ", count); + /* If tagging of traffic class is enabled tc will print number of + transmission - otherwise it will be 0 */ + LOG_INFO("Received response %u (tc:%d) from ", count, + uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS)); LOG_INFO_6ADDR(sender_addr); LOG_INFO_("\n"); } @@ -42,6 +45,7 @@ PROCESS_THREAD(udp_client_process, ev, data) { static struct etimer periodic_timer; static unsigned count; + uip_ipaddr_t dest_ipaddr; PROCESS_BEGIN(); @@ -53,19 +57,21 @@ PROCESS_THREAD(udp_client_process, ev, data) while(1) { PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&periodic_timer)); - if(rpl_is_reachable()) { + if(NETSTACK_ROUTING.node_is_reachable() && NETSTACK_ROUTING.get_root_ipaddr(&dest_ipaddr)) { /* Send to DAG root */ - rpl_dag_t *dag = rpl_get_any_dag(); - if(dag != NULL) { /* Only a sanity check. Should never be NULL - as rpl_is_reachable() is true */ - LOG_INFO("Sending request %u to ", count); - LOG_INFO_6ADDR(&dag->dag_id); - LOG_INFO_("\n"); - simple_udp_sendto(&udp_conn, &count, sizeof(count), &dag->dag_id); - count++; - } + LOG_INFO("Sending request %u to ", count); + LOG_INFO_6ADDR(&dest_ipaddr); + LOG_INFO_("\n"); + /* Set the number of transmissions to use for this packet - + this can be used to create more reliable transmissions or + less reliable than the default. Works end-to-end if + UIP_CONF_TAG_TC_WITH_VARIABLE_RETRANSMISSIONS is set to 1. + */ + uipbuf_set_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS, 1 + count % 5); + simple_udp_sendto(&udp_conn, &count, sizeof(count), &dest_ipaddr); + count++; } else { - LOG_INFO("Not reachable yet %p\n", rpl_get_any_dag()); + LOG_INFO("Not reachable yet\n"); } /* Add some jitter */ diff --git a/examples/rpl-udp/udp-server.c b/examples/rpl-udp/udp-server.c index 222556d59638ff7d9ee3e984ce19709a4a67ff75..399cabfc4c3156ae9f24bde6ab556c77e0663fd5 100644 --- a/examples/rpl-udp/udp-server.c +++ b/examples/rpl-udp/udp-server.c @@ -28,8 +28,7 @@ */ #include "contiki.h" -#include "rpl.h" -#include "rpl-dag-root.h" +#include "net/routing/routing.h" #include "net/netstack.h" #include "net/ipv6/simple-udp.h" @@ -72,7 +71,7 @@ PROCESS_THREAD(udp_server_process, ev, data) PROCESS_BEGIN(); /* Initialize DAG root */ - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_start(); /* Initialize UDP connection */ simple_udp_register(&udp_conn, UDP_SERVER_PORT, NULL, diff --git a/examples/sensniff/Makefile b/examples/sensniff/Makefile index 2bb2549b110f42c7a6356d39c177d322f78c6294..e207590bbad2ebd188c1f87440cdb724c152bd6b 100644 --- a/examples/sensniff/Makefile +++ b/examples/sensniff/Makefile @@ -1,14 +1,12 @@ CONTIKI_PROJECT = sensniff CONTIKI = ../.. -PROJECT_SOURCEFILES += sensniff-mac.c netstack.c -PROJECTDIRS += pool $(TARGET) +PLATFORMS_ONLY = cc2538dk openmote-cc2538 zoul srf06-cc26xx jn516x --include $(CONTIKI)/Makefile.identify-target +PROJECT_SOURCEFILES += sensniff-mac.c netstack.c +MODULES_REL += pool $(TARGET) -### Optionally, the target can add its own Makefile, to do things like e.g. -### add more source files to the build or define make variables. --include $(TARGET)/Makefile.$(TARGET) +include $(CONTIKI)/Makefile.identify-target all: $(CONTIKI_PROJECT) diff --git a/examples/sensniff/README.md b/examples/sensniff/README.md index 3fe1df7dd1484d7cc364971bdac994dc0fa42205..01b3de54ccd0db857bc467b39448329a6e47a2c2 100644 --- a/examples/sensniff/README.md +++ b/examples/sensniff/README.md @@ -2,7 +2,8 @@ sensniff Contiki Project ======================== This example can be used to create an IEEE 802.15.4 wireless sniffer firmware, meant to be used in parallel with -[sensniff](https://github.com/g-oikonomou/sensniff). +[sensniff](https://github.com/g-oikonomou/sensniff). Sensniff is distributed +standalone, but also as part of Contiki-NG under `tools/sensniff`. Running ======= diff --git a/examples/slip-radio/Makefile b/examples/slip-radio/Makefile index d59b5e2402e3518599c6a97cb6f1bc5cb5b9c897..877b109f111ec711b0eb139b688c478d1fee9d13 100644 --- a/examples/slip-radio/Makefile +++ b/examples/slip-radio/Makefile @@ -2,17 +2,16 @@ CONTIKI_PROJECT=slip-radio all: $(CONTIKI_PROJECT) MODULES += os/services/slip-cmd -CONTIKI=../.. --include $(CONTIKI)/Makefile.identify-target +# slip-radio is only intended for platforms with SLIP support +PLATFORMS_EXCLUDE = native nrf52dk -### Optionally, the target can add its own Makefile, to do things like e.g. -### add more source files to the build or define make variables. --include $(TARGET)/Makefile.$(TARGET) +CONTIKI=../.. +include $(CONTIKI)/Makefile.identify-target -PROJECTDIRS += $(TARGET) +MODULES_REL += $(TARGET) PROJECT_SOURCEFILES += slip-net.c # custom net layer, but with IPv6 enabled MAKE_NET = MAKE_NET_IPV6 -MAKE_ROUTING = MAKE_ROUTING_NONE +MAKE_ROUTING = MAKE_ROUTING_NULLROUTING include $(CONTIKI)/Makefile.include diff --git a/examples/slip-radio/project-conf.h b/examples/slip-radio/project-conf.h index 89e135a424458c0a5e4ac20e62b6286dae2e7777..4283d0249e9919fcfb7fb3caa342429a4254519f 100644 --- a/examples/slip-radio/project-conf.h +++ b/examples/slip-radio/project-conf.h @@ -29,15 +29,11 @@ #ifndef PROJECT_CONF_H_ #define PROJECT_CONF_H_ -/*---------------------------------------------------------------------------*/ -/* Include target-specific header */ -#ifdef TARGET_CONF_PATH -#include TARGET_CONF_PATH -#endif /* TARGET_CONF_PATH */ + /*---------------------------------------------------------------------------*/ #define UIP_CONF_ROUTER 0 -#define CMD_CONF_OUTPUT slip_radio_cmd_output +#define CMD_CONF_OUTPUT slip_write /* Default CMD handlers if the target did not specify them */ #ifndef CMD_CONF_HANDLERS diff --git a/examples/slip-radio/sky/Makefile.sky b/examples/slip-radio/sky/Makefile.sky deleted file mode 100644 index 83a91472d291bbb4532afc999ec3c7291a900425..0000000000000000000000000000000000000000 --- a/examples/slip-radio/sky/Makefile.sky +++ /dev/null @@ -1,4 +0,0 @@ -PROJECT_SOURCEFILES += slip-radio-cc2420.c slip-radio-sky-sensors.c -PROJECT_SOURCEFILES += slip-radio-putchar.c - -CFLAGS += -DTARGET_CONF_PATH=\"target-conf.h\" diff --git a/examples/slip-radio/sky/module-macros.h b/examples/slip-radio/sky/module-macros.h new file mode 100644 index 0000000000000000000000000000000000000000..1fabdf1cfcab80bb58722c4dcbc8f7fdad9ab71e --- /dev/null +++ b/examples/slip-radio/sky/module-macros.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#define QUEUEBUF_CONF_NUM 4 +#define UIP_CONF_BUFFER_SIZE 140 + +#define UART1_CONF_RX_WITH_DMA 1 +/*---------------------------------------------------------------------------*/ diff --git a/examples/slip-radio/sky/slip-radio-cc2420.c b/examples/slip-radio/sky/slip-radio-cc2420.c deleted file mode 100644 index f49e3c4e986e8b81c489ff7f32bace5282529187..0000000000000000000000000000000000000000 --- a/examples/slip-radio/sky/slip-radio-cc2420.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2011, Swedish Institute of Computer Science - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - * Sets up some commands for the CC2420 radio chip. - */ - -#include "contiki.h" -#include "cc2420.h" -#include "cmd.h" -#include <stdio.h> - -int -cmd_handler_cc2420(const uint8_t *data, int len) -{ - if(data[0] == '!') { - if(data[1] == 'C') { - printf("cc2420_cmd: setting channel: %d\n", data[2]); - cc2420_set_channel(data[2]); - return 1; - } - } else if(data[0] == '?') { - if(data[1] == 'C') { - uint8_t buf[4]; - printf("cc2420_cmd: getting channel: %d\n", data[2]); - buf[0] = '!'; - buf[1] = 'C'; - buf[2] = cc2420_get_channel(); - cmd_send(buf, 3); - return 1; - } - } - return 0; -} diff --git a/examples/slip-radio/sky/slip-radio-sky-sensors.c b/examples/slip-radio/sky/slip-radio-sky-sensors.c deleted file mode 100644 index 9cf23874119600a88f140059cf72746761adff39..0000000000000000000000000000000000000000 --- a/examples/slip-radio/sky/slip-radio-sky-sensors.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2011, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "contiki.h" -#include "lib/sensors.h" -#include "dev/sht11/sht11-sensor.h" -#include "slip-radio.h" -#include "cmd.h" -#include <stdio.h> - -/*---------------------------------------------------------------------------*/ -static void -init(void) -{ -} -/*---------------------------------------------------------------------------*/ -static int -write_percent_float(char *data, int maxlen, int temp) -{ - int t; - t = temp % 100; - if(t < 0) { - t = -t; - } - return snprintf(data, maxlen, "%d.%02d", temp / 100, t); -} -/*---------------------------------------------------------------------------*/ -static void -send(void) -{ -#define MAX_SIZE 40 - char data[MAX_SIZE]; - int temperature; - int ms; - long hum; - int pos = 0; - - /* SENSORS_ACTIVATE(light_sensor); */ - SENSORS_ACTIVATE(sht11_sensor); - - pos += snprintf(data, MAX_SIZE, "!D"); - /* int light1 = light_sensor.value(LIGHT_SENSOR_PHOTOSYNTHETIC); */ - /* int light2 = light_sensor.value(LIGHT_SENSOR_TOTAL_SOLAR); */ - temperature = -3970 + sht11_sensor.value(SHT11_SENSOR_TEMP); - ms = sht11_sensor.value(SHT11_SENSOR_HUMIDITY); - /* this is in * 10000 */ - /* -2.0468 + 0.0367 * ms + -1.5955e-6 * ms * ms ...too small value... */ - hum = (-20468L + 367L * ms) / 100L; - - /* SENSORS_DEACTIVATE(light_sensor); */ - SENSORS_DEACTIVATE(sht11_sensor); - - pos += snprintf(&data[pos], MAX_SIZE - pos, "temp="); - pos += write_percent_float(&data[pos], MAX_SIZE - pos, temperature); - pos += snprintf(&data[pos], MAX_SIZE - pos, ";hum="); - pos += write_percent_float(&data[pos], MAX_SIZE - pos, hum); - - cmd_send((uint8_t *)data, pos); -} -/* ---------------------------------------------------------------------- */ -const struct slip_radio_sensors slip_radio_sky_sensors = { - init, send -}; -/* ---------------------------------------------------------------------- */ diff --git a/examples/slip-radio/slip-net.c b/examples/slip-radio/slip-net.c index 1a787c85c1b5de1cb3cab4ef25c76fe0c3baa9ec..edf2191061183d1b719401d169dca03153d6376e 100644 --- a/examples/slip-radio/slip-net.c +++ b/examples/slip-radio/slip-net.c @@ -49,27 +49,6 @@ slipnet_init(void) { } /*---------------------------------------------------------------------------*/ -void -slip_send_packet(const uint8_t *ptr, int len) -{ - uint16_t i; - uint8_t c; - - slip_arch_writeb(SLIP_END); - for(i = 0; i < len; ++i) { - c = *ptr++; - if(c == SLIP_END) { - slip_arch_writeb(SLIP_ESC); - c = SLIP_ESC_END; - } else if(c == SLIP_ESC) { - slip_arch_writeb(SLIP_ESC); - c = SLIP_ESC_ESC; - } - slip_arch_writeb(c); - } - slip_arch_writeb(SLIP_END); -} -/*---------------------------------------------------------------------------*/ static void slipnet_input(void) { @@ -85,7 +64,7 @@ slipnet_input(void) packetbuf_datalen(), i); for(i = 0; i < uip_len; i++) { - LOG_DBG("%02x", (unsigned char)uip_buf[i]); + LOG_DBG_("%02x", (unsigned char)uip_buf[i]); if((i & 15) == 15) { LOG_DBG_("\n"); } else if((i & 7) == 7) { @@ -94,7 +73,7 @@ slipnet_input(void) } LOG_DBG_("\n"); - slip_send_packet(uip_buf, uip_len); + slip_write(uip_buf, uip_len); } /*---------------------------------------------------------------------------*/ static uint8_t diff --git a/examples/slip-radio/slip-radio.c b/examples/slip-radio/slip-radio.c index 720bc969486077309f2a1fcf7dc7302056941ed5..b39032d96d1fc09a041627673497c2d5370f0127 100644 --- a/examples/slip-radio/slip-radio.c +++ b/examples/slip-radio/slip-radio.c @@ -56,8 +56,6 @@ extern const struct slip_radio_sensors SLIP_RADIO_CONF_SENSORS; #endif -void slip_send_packet(const uint8_t *ptr, int len); - /* max 16 packets at the same time??? */ uint8_t packet_ids[16]; int packet_pos; @@ -168,10 +166,29 @@ slip_radio_cmd_handler(const uint8_t *data, int len) packet_pos = 0; } + return 1; + } else if(data[1] == 'V') { + int type = ((uint16_t)data[2] << 8) | data[3]; + int value = ((uint16_t)data[4] << 8) | data[5]; + int param = type; /* packetutils_to_radio_param(type); */ + if(param < 0) { + printf("radio: unknown parameter %d (can not set to %d)\n", type, value); + } else { + if(param == RADIO_PARAM_RX_MODE) { + printf("radio: setting rxmode to 0x%x\n", value); + } else if(param == RADIO_PARAM_PAN_ID) { + printf("radio: setting pan id to 0x%04x\n", value); + } else if(param == RADIO_PARAM_CHANNEL) { + printf("radio: setting channel: %u\n", value); + } else { + printf("radio: setting param %d to %d (0x%02x)\n", param, value, value); + } + NETSTACK_RADIO.set_value(param, value); + } return 1; } - } else if(uip_buf[0] == '?') { - LOG_DBG("Got request message of type %c\n", uip_buf[1]); + } else if(data[0] == '?') { + LOG_DBG("Got request message of type %c\n", data[1]); if(data[1] == 'M') { /* this is just a test so far... just to see if it works */ uip_buf[0] = '!'; @@ -182,22 +199,38 @@ slip_radio_cmd_handler(const uint8_t *data, int len) uip_len = 10; cmd_send(uip_buf, uip_len); return 1; + } else if(data[1] == 'V') { + /* ask the radio about the specific parameter and send it back... */ + int type = ((uint16_t)data[2] << 8) | data[3]; + int value; + int param = type; /* packetutils_to_radio_param(type); */ + if(param < 0) { + printf("radio: unknown parameter %d\n", type); + } + + NETSTACK_RADIO.get_value(param, &value); + + uip_buf[0] = '!'; + uip_buf[1] = 'V'; + uip_buf[2] = type >> 8; + uip_buf[3] = type & 0xff; + uip_buf[4] = value >> 8; + uip_buf[5] = value & 0xff; + uip_len = 6; + cmd_send(uip_buf, uip_len); } } return 0; } /*---------------------------------------------------------------------------*/ -void -slip_radio_cmd_output(const uint8_t *data, int data_len) -{ - slip_send_packet(data, data_len); -} -/*---------------------------------------------------------------------------*/ static void slip_input_callback(void) { - LOG_DBG("SR-SIN: %u '%c%c'\n", uip_len, uip_buf[0], uip_buf[1]); - cmd_input(uip_buf, uip_len); + LOG_DBG("SR-SIN: %u '%c%c'\n", uip_len, + uip_buf[UIP_LLH_LEN], uip_buf[UIP_LLH_LEN + 1]); + if(!cmd_input(&uip_buf[UIP_LLH_LEN], uip_len)) { + cmd_send((uint8_t *)"EUnknown command", 16); + } uip_clear_buf(); } /*---------------------------------------------------------------------------*/ @@ -222,7 +255,7 @@ PROCESS_THREAD(slip_radio_process, ev, data) #ifdef SLIP_RADIO_CONF_SENSORS SLIP_RADIO_CONF_SENSORS.init(); #endif - printf("Slip Radio started...\n"); + LOG_INFO("Slip Radio started\n"); etimer_set(&et, CLOCK_SECOND * 3); diff --git a/examples/storage/antelope-shell/Makefile b/examples/storage/antelope-shell/Makefile index c6ffd276bbca7081467b2fb9d124efca83daa12d..5eff3dcd3e9b59cea2892cf91aec654d2ecadbbb 100644 --- a/examples/storage/antelope-shell/Makefile +++ b/examples/storage/antelope-shell/Makefile @@ -2,6 +2,10 @@ CONTIKI = ../../.. MODULES += os/storage/antelope os/services/unit-test -all: shell-db +# does not fit on Sky +PLATFORMS_ONLY= cc2538dk zoul + +CONTIKI_PROJECT = shell-db +all: $(CONTIKI_PROJECT) include $(CONTIKI)/Makefile.include diff --git a/examples/storage/cfs-coffee/Makefile b/examples/storage/cfs-coffee/Makefile index 4d27d6f8f03b4a5d520e4c012b915000b7f1ed87..b6d22f5ac78acb4eb8542f87998eacb77ffaa363 100644 --- a/examples/storage/cfs-coffee/Makefile +++ b/examples/storage/cfs-coffee/Makefile @@ -1,7 +1,11 @@ CONTIKI = ../../.. +PLATFORMS_ONLY= cc2538dk zoul sky + MODULES += os/services/unit-test +MODULES += os/storage/cfs -all: test-cfs test-coffee example-coffee +CONTIKI_PROJECT = test-cfs test-coffee example-coffee +all: $(CONTIKI_PROJECT) include $(CONTIKI)/Makefile.include diff --git a/examples/storage/cfs-coffee/README.md b/examples/storage/cfs-coffee/README.md index 991e9583b81c8866ae04ff3d283dc4109636173e..028f518f83d024246595e22be706e71d9ab21ee2 100644 --- a/examples/storage/cfs-coffee/README.md +++ b/examples/storage/cfs-coffee/README.md @@ -23,6 +23,9 @@ Supported Hardware (tested or known to work) * cc2538dk * openmote-cc2538 * zoul +* TI srf06-cc26xx + - sensortag + - launchpad The examples are known to build for the 'avr-raven' platform. However, some of them currently fail at runtime due to file system overflow. diff --git a/examples/websocket/Makefile b/examples/websocket/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..87d0789c19c35c28e489b3cfe5db5d2b6de076fb --- /dev/null +++ b/examples/websocket/Makefile @@ -0,0 +1,8 @@ +CONTIKI_PROJECT = http-example websocket-example +all: $(CONTIKI_PROJECT) +CONTIKI=../.. +MODULES += os/net/app-layer/http-socket + +PLATFORMS_EXCLUDE = sky + +include $(CONTIKI)/Makefile.include diff --git a/examples/http-socket/http-example.c b/examples/websocket/http-example.c similarity index 100% rename from examples/http-socket/http-example.c rename to examples/websocket/http-example.c diff --git a/examples/http-socket/project-conf.h b/examples/websocket/project-conf.h similarity index 100% rename from examples/http-socket/project-conf.h rename to examples/websocket/project-conf.h diff --git a/examples/http-socket/websocket-example.c b/examples/websocket/websocket-example.c similarity index 100% rename from examples/http-socket/websocket-example.c rename to examples/websocket/websocket-example.c diff --git a/examples/websocket/websocket-node/Makefile b/examples/websocket/websocket-node/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..9dcc1def8bc5811d492b6c0f923ea45b06623f36 --- /dev/null +++ b/examples/websocket/websocket-node/Makefile @@ -0,0 +1,13 @@ +install: + npm install websocket + + +run: + nodejs example-server.js + +# Needed by the build all script +all: + true + +clean: + rm -rf node_modules diff --git a/examples/http-socket/websocket-node/example-server.js b/examples/websocket/websocket-node/example-server.js similarity index 100% rename from examples/http-socket/websocket-node/example-server.js rename to examples/websocket/websocket-node/example-server.js diff --git a/os/contiki-default-conf.h b/os/contiki-default-conf.h index 0395f6ca4ffa4e78e39afb496a9950687cee4cd4..8ec1a41f7084e06e7e82071845555fe06018ec06 100644 --- a/os/contiki-default-conf.h +++ b/os/contiki-default-conf.h @@ -81,6 +81,10 @@ #define UIP_CONF_ROUTER 1 #endif /* UIP_CONF_ROUTER */ +/* UIP_CONF_IPV6_RPL tells whether the RPL routing protocol is running, + whether implemented as RPL Lite or RPL Classic */ +#define UIP_CONF_IPV6_RPL (ROUTING_CONF_RPL_LITE || ROUTING_CONF_RPL_CLASSIC) + /* If RPL is enabled also enable the RPL NBR Policy */ #if UIP_CONF_IPV6_RPL #ifndef NBR_TABLE_FIND_REMOVABLE diff --git a/os/contiki-main.c b/os/contiki-main.c index a995d5ee515c38f34bd496e3bafd9c0a9ac06d6c..234b759ee11c984bcc208e1dcf7b3cc72ac94e61 100644 --- a/os/contiki-main.c +++ b/os/contiki-main.c @@ -44,14 +44,12 @@ #include "contiki-net.h" #include "sys/platform.h" #include "sys/energest.h" +#include "sys/stack-check.h" #include "dev/watchdog.h" -#if BUILD_WITH_ORCHESTRA -#include "os/services/orchestra/orchestra.h" -#endif /* BUILD_WITH_ORCHESTRA */ -#if BUILD_WITH_SHELL -#include "os/services/shell/serial-shell.h" -#endif /* BUILD_WITH_SHELL */ +#include "services/rpl-border-router/rpl-border-router.h" +#include "services/orchestra/orchestra.h" +#include "services/shell/serial-shell.h" #include <stdio.h> #include <stdint.h> @@ -81,14 +79,16 @@ main(void) energest_init(); +#if STACK_CHECK_ENABLED + stack_check_init(); +#endif + platform_init_stage_two(); LOG_INFO("Starting " CONTIKI_VERSION_STRING "\n"); - LOG_INFO(" Net: "); - LOG_INFO_("%s\n", NETSTACK_NETWORK.name); - LOG_INFO(" MAC: "); - LOG_INFO_("%s\n", NETSTACK_MAC.name); + LOG_INFO(" Net: %s\n", NETSTACK_NETWORK.name); + LOG_INFO(" MAC: %s\n", NETSTACK_MAC.name); netstack_init(); @@ -111,6 +111,11 @@ main(void) platform_init_stage_three(); +#if BUILD_WITH_RPL_BORDER_ROUTER + rpl_border_router_init(); + LOG_DBG("With RPL Border Router\n"); +#endif /* BUILD_WITH_RPL_BORDER_ROUTER */ + #if BUILD_WITH_ORCHESTRA orchestra_init(); LOG_DBG("With Orchestra\n"); diff --git a/os/contiki-net.h b/os/contiki-net.h index 9b467363f9c76558b385aa83576931b621dcec0b..1eb50dd8d0aaeba60d0a6000787892d985d91f58 100644 --- a/os/contiki-net.h +++ b/os/contiki-net.h @@ -42,6 +42,7 @@ #include "net/ipv6/uip-udp-packet.h" #include "net/ipv6/simple-udp.h" #include "net/ipv6/uip-nameserver.h" +#include "net/routing/routing.h" #if NETSTACK_CONF_WITH_IPV6 #include "net/ipv6/uip-icmp6.h" diff --git a/os/dev/ble-hal.h b/os/dev/ble-hal.h new file mode 100644 index 0000000000000000000000000000000000000000..ce5f5e8b172a0c0a1d55d764c1f28b700cc9bab0 --- /dev/null +++ b/os/dev/ble-hal.h @@ -0,0 +1,404 @@ +/* + * Copyright (c) 2017, Graz University of Technology + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * hardware abstraction for a BLE controller + * + * \author + * Michael Spoerk <michael.spoerk@tugraz.at> + */ +/*---------------------------------------------------------------------------*/ + +#ifndef BLE_HAL_H_ +#define BLE_HAL_H_ + +#include <stddef.h> + +/*---------------------------------------------------------------------------*/ +/* BLE device address size */ +#define BLE_ADDR_SIZE 6 +/*---------------------------------------------------------------------------*/ +/* Advertisement channel definitions */ +#define BLE_ADV_DATA_LEN 31 +#define BLE_SCAN_RESP_DATA_LEN 31 +#define BLE_ADV_CHANNEL_1 37 +#define BLE_ADV_CHANNEL_1_MASK 0b001 +#define BLE_ADV_CHANNEL_2 38 +#define BLE_ADV_CHANNEL_2_MASK 0b010 +#define BLE_ADV_CHANNEL_3 39 +#define BLE_ADV_CHANNEL_3_MASK 0b100 +#define BLE_ADV_INTERVAL_MIN 20 +#define BLE_ADV_INTERVAL_MAX 0x4000 +#define BLE_SCAN_INTERVAL_MIN 0x0004 +#define BLE_SCAN_INTERVAL_MAX 0x4000 +/*---------------------------------------------------------------------------*/ +/* Data channel definitions */ +#define BLE_DATA_CHANNEL_MIN 0 +#define BLE_DATA_CHANNEL_MAX 36 +/* Types of data PDU frames */ +#define BLE_DATA_PDU_LLID_DATA_FRAGMENT 0b01 +#define BLE_DATA_PDU_LLID_DATA_MESSAGE 0b10 +#define BLE_DATA_PDU_LLID_CONTROL 0b11 +/*---------------------------------------------------------------------------*/ +/* Types of LL control PDUs */ +#define BLE_LL_CONN_UPDATE_REQ 0x00 +#define BLE_LL_CHANNEL_MAP_REQ 0x01 +#define BLE_LL_TERMINATE_IND 0x02 +#define BLE_LL_ENC_REQ 0x03 +#define BLE_LL_ENC_RSP 0x04 +#define BLE_LL_START_ENC_REQ 0x05 +#define BLE_LL_START_ENC_RSP 0x06 +#define BLE_LL_UNKNOWN_RSP 0x07 +#define BLE_LL_FEATURE_REQ 0x08 +#define BLE_LL_FEATURE_RSP 0x09 +#define BLE_LL_PAUSE_ENC_REQ 0x0A +#define BLE_LL_PAUSE_ENC_RSP 0x0B +#define BLE_LL_VERSION_IND 0x0C +#define BLE_LL_REJECT_IND 0x0D +#define BLE_LL_SLAVE_FEATURE_REQ 0x0E +#define BLE_LL_CONN_PARAM_REQ 0x0F +#define BLE_LL_CONN_PARAM_RSP 0x10 +#define BLE_LL_REJECT_IND_EXT 0x11 +#define BLE_LL_PING_REQ 0x12 +#define BLE_LL_PING_RSP 0x13 +/*---------------------------------------------------------------------------*/ +#define FRAME_BLE_RX_EVENT 0x00 /* signaling that data was received (standard) */ +#define FRAME_BLE_TX_EVENT 0x10 /* signaling that data was successfully sent */ +#define FRAME_BLE_CONNECTION_EVENT 0x20 /* signaling that a new BLE connection was established */ +#define FRAME_BLE_CONNECTION_UPDATED 0x30 /* signaling that the BLE connection parameter were successfully updated */ +/*---------------------------------------------------------------------------*/ +/* Return values for functions of ble_controller_driver implementations */ +typedef enum { + BLE_RESULT_OK, + BLE_RESULT_NOT_SUPPORTED, + BLE_RESULT_INVALID_PARAM, + BLE_RESULT_ERROR +} ble_result_t; + +/*---------------------------------------------------------------------------*/ +/* Type of BLE device address */ +typedef enum { + BLE_ADDR_TYPE_PUBLIC, + BLE_ADDR_TYPE_RANDOM +} ble_addr_type_t; + +/*---------------------------------------------------------------------------*/ +/* Advertising modes of BLE */ +typedef enum { + /* connectable undirected advertising */ + BLE_ADV_IND, + + /* connectable directed advertising (high duty cycle) */ + BLE_ADV_DIR_IND_HDC, + + /* scannable undirected advertising */ + BLE_ADV_SCAN_IND, + + /* non connectable undirected advertising */ + BLE_ADV_NONCONN_IND, + + /* connectable directed advertising (low duty cycle) */ + BLE_ADV_DIR_IND_LDC +} ble_adv_type_t; + +/*---------------------------------------------------------------------------*/ +/* Scanning modes of BLE */ +typedef enum { + /* no SCAN REQUESTS are sent */ + BLE_SCAN_PASSIVE, + /* SCAN REQUESTS may be sent */ + BLE_SCAN_ACTIVE +} ble_scan_type_t; + +/*---------------------------------------------------------------------------*/ +/* Scanning filter policy */ +typedef enum { + /* accept all advertisement packets */ + BLE_SCAN_FILTER_POLICY_ACCEPT, + /* ignore all advertisement packets from devices not on the white list */ + BLE_SCAN_FILTER_POLICY_IGNORE +} ble_scan_filter_policy_t; +/*---------------------------------------------------------------------------*/ +/* List of packets to be sent by RDC layer */ +struct ble_buf_list { + struct ble_buf_list *next; + struct queuebuf *buf; + void *ptr; +}; + +/*---------------------------------------------------------------------------*/ +/* Extension of the RADIO_PARAM fields for the BLE radios */ +enum { + /* start with 100 to be sure to not interfere with the standard values*/ + /*-----------------------------------------------------------------------*/ + /* BLE controller general */ + /* The bluetooth device address */ + RADIO_CONST_BLE_BD_ADDR = 100, + + /* the size of a single BLE command buffer */ + RADIO_CONST_BLE_BUFFER_SIZE, + + /* the amount of single BLE command buffers */ + RADIO_CONST_BLE_BUFFER_AMOUNT, + + /*-----------------------------------------------------------------------*/ + /* BLE advertisement */ + + /* advertisement interval */ + RADIO_PARAM_BLE_ADV_INTERVAL, + + /* BLE advertisement type (directed/undirected, ...) */ + RADIO_PARAM_BLE_ADV_TYPE, + + /* type of own address during advertisement */ + RADIO_PARAM_BLE_ADV_OWN_ADDR_TYPE, + + /* advertisement channel map */ + RADIO_PARAM_BLE_ADV_CHANNEL_MAP, + + /* advertisement payload */ + RADIO_PARAM_BLE_ADV_PAYLOAD, + + /* scan response payload */ + RADIO_PARAM_BLE_ADV_SCAN_RESPONSE, + + /* 1: enable advertisement / 0: disable advertisement */ + RADIO_PARAM_BLE_ADV_ENABLE, + + /*-----------------------------------------------------------------------*/ + /* BLE scanning */ + + /* scanning interval */ + RADIO_PARAM_BLE_SCAN_INTERVAL, + + /* scanning window */ + RADIO_PARAM_BLE_SCAN_WINDOW, + + /* BLE scanning type (active/passive) */ + RADIO_PARAM_BLE_SCAN_TYPE, + + /* type of own address during scanning */ + RADIO_PARAM_BLE_SCAN_OWN_ADDR_TYPE, + + /* scanning channel */ + RADIO_PARAM_BLE_SCAN_CHANNEL, + + /* 1: enable scanning / 0: disable scanning */ + RADIO_PARAM_BLE_SCAN_ENABLE, + + /*-----------------------------------------------------------------------*/ + /* BLE initiating */ + /* The initiating command uses some parameters from scanning */ + /* (scan interval, window, address type) */ + + /* address type of the advertising device */ + RADIO_PARAM_BLE_PEER_ADDR_TYPE, + + /* address of the advertising device */ + RADIO_PARAM_BLE_PEER_ADDR, + + /* connection interval */ + RADIO_PARAM_BLE_CONN_INTERVAL, + + /* slave latency */ + RADIO_PARAM_BLE_CONN_LATENCY, + + /* supervision timeout */ + RADIO_PARAM_BLE_CONN_SUPERVISION_TIMEOUT, + + /* 1: start connection / 0: cancel connection creation */ + RADIO_PARAM_BLE_INITIATOR_ENABLE, + + RADIO_PARAM_BLE_CONN_UPDATE +}; + +/*---------------------------------------------------------------------------*/ +/** + * The structure of a ble radio controller driver in Contiki. + */ +struct ble_hal_driver { + + /*------------------------------------------------------------------------*/ + /* GENERAL COMMANDS */ + /** + * Resets the BLE controller + */ + ble_result_t (*reset)(void); + + /** + * Reads the static BLE device address. + * + * \param addr the static device address + */ + ble_result_t (*read_bd_addr)(uint8_t *addr); + + /** + * Reads the size of the data buffers. + * + * \param buf_len the length of a single data buffer + * \param num_buf the number of data buffers + */ + ble_result_t (*read_buffer_size) (unsigned int *buf_len, + unsigned int *num_buf); + + /*------------------------------------------------------------------------*/ + /* ADVERTISING COMMANDS */ + /** + * Sets the parameter for advertising. + * + * \param adv_interval advertising interval + * (interval = adv_interval * 0.625 ms) + * \param type type of advertising + * \param own_addr_type indicator if own address is public/random + * \param adv_channel_map map of advertising channels to use + */ + ble_result_t (*set_adv_param) (unsigned int adv_interval, + ble_adv_type_t type, + ble_addr_type_t own_addr_type, + unsigned short adv_channel_map); + + /** + * Reads the used power on the advertisement channels. + * + * \param power the used power in dBm + */ + ble_result_t (*read_adv_channel_tx_power) (short *power); + + /** + * Sets the advertising data. + * + * \param data_len the length of the advertising data + * \param data the data to advertise + */ + ble_result_t (*set_adv_data) (unsigned short data_len, + char *data); + + /** + * Sets the scan response data. + * + * \param data_len the length of the scan response data + * \param data the data of a scan response + */ + ble_result_t (*set_scan_resp_data) (unsigned short data_len, + char *data); + + /** + * Enables/disables advertising. + * + * \param enable if 1 then enable advertising, otherwise disable + */ + ble_result_t (*set_adv_enable) (unsigned short enable); + + /*------------------------------------------------------------------------*/ + /* SCANNING COMMANDS */ + /** + * Sets the parameter for scanning. + * + * \param type scan mode + * \param scan_interval scan interval (interval = scan_interval * 0.625 ms) + * \param scan_window scan window (window = scan_window * 0.625 ms) + * \param own_addr_type indicator if own address is public/random + */ + ble_result_t (*set_scan_param) (ble_scan_type_t type, + unsigned int scan_interval, + unsigned int scan_window, + ble_addr_type_t own_addr_type); + + /** + * Enables/disables scanning. + * + * \param enable 1: enable scanning, otherwise disable + * \param filter_duplicates: 1: filter duplicates, otherwise no filtering + */ + ble_result_t (*set_scan_enable) (unsigned short enable, + unsigned short filter_duplicates); + + /*------------------------------------------------------------------------*/ + /* INITIATING COMMANDS */ + /** + * Initiates the creation of a BLE connection. + * + * \param scan_interval scan interval (interval = scan_interval * 0.625 ms) + * \param scan_window scan window (window = scan_window * 0.625 ms) + * \param peer_addr_type indicator if peer address is public/random + * \param peer_addr ble address of the device to connect to + * \param own_addr_type indicator if own address is public/random + * \param conn_interval connection interval + * (interval = conn_interval * 1.25 ms) + * \param conn_latency slave latency + * \param supervision_timeout (timeout = supervision_timeout * 10 ms) + */ + ble_result_t (*create_connection) (unsigned int scan_interval, + unsigned int scan_window, + ble_addr_type_t peer_addr_type, + uint8_t *peer_addr, + ble_addr_type_t own_addr_type, + unsigned int conn_interval, + unsigned int conn_latency, + unsigned int supervision_timeout); + + /** + * Cancels the initiation of a BLE connection. + */ + ble_result_t (*create_connection_cancel) (void); + + /*------------------------------------------------------------------------*/ + /* CONNECTION COMMANDS */ + /** + * Updates the connection parameters. + * \param conn_interval connection interval + * (interval = conn_interval * 1.25 ms) + * \param conn_latency slave latency + * \param supervision_timeout (timeout = supervision_timeout * 10 ms) + */ + ble_result_t (*connection_update) (unsigned int connection_handle, + unsigned int conn_interval, + unsigned int conn_latency, + unsigned int supervision_timeout); + + /** + * Disconnects the connection. + * + * \param connection_handle + * \param reason see error codes of Bluetooth specification + */ + ble_result_t (*disconnect) (unsigned int connection_handle, + unsigned short reason); + + ble_result_t (*send) (void *buf, unsigned short buf_len); + + ble_result_t (*send_list) (struct ble_buf_list *list); + + ble_result_t (*read_connection_interval) (unsigned int conn_handle, + unsigned int *conn_interval_ms); +}; + +#endif /* BLE_HAL_H_ */ diff --git a/os/dev/button-hal.c b/os/dev/button-hal.c new file mode 100644 index 0000000000000000000000000000000000000000..58cded79023b43c137b40957d468faa7ed2a3485 --- /dev/null +++ b/os/dev/button-hal.c @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup button_hal + * @{ + * + * \file + * Platform-independent button driver. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "sys/process.h" +#include "sys/ctimer.h" +#include "sys/critical.h" +#include "dev/gpio-hal.h" +#include "dev/button-hal.h" + +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +/*---------------------------------------------------------------------------*/ +PROCESS(button_hal_process, "Button HAL process"); +/*---------------------------------------------------------------------------*/ +process_event_t button_hal_press_event; +process_event_t button_hal_release_event; +process_event_t button_hal_periodic_event; +/*---------------------------------------------------------------------------*/ +/* A mask of all pins that have changed state since the last process poll */ +static volatile gpio_hal_pin_mask_t pmask; +/*---------------------------------------------------------------------------*/ +extern button_hal_button_t *button_hal_buttons[]; +/*---------------------------------------------------------------------------*/ +/* Common handler for all handler events, and register it with the GPIO HAL */ +static gpio_hal_event_handler_t button_event_handler; +/*---------------------------------------------------------------------------*/ +static void +duration_exceeded_callback(void *btn) +{ + button_hal_button_t *button = (button_hal_button_t *)btn; + + button->press_duration_seconds++; + ctimer_set(&button->duration_ctimer, CLOCK_SECOND, + duration_exceeded_callback, button); + process_post(PROCESS_BROADCAST, button_hal_periodic_event, button); +} +/*---------------------------------------------------------------------------*/ +static void +debounce_handler(void *btn) +{ + button_hal_button_t *button; + int expired; + uint8_t button_state; + + button = (button_hal_button_t *)btn; + + /* + * A new debounce may have been triggered after expiration of the previous + * one but before we got called. + */ + if(!ctimer_expired(&button->debounce_ctimer)) { + return; + } + + expired = ctimer_expired(&button->duration_ctimer); + + button_state = button_hal_get_state(button); + + /* + * A debounce timer expired. Inspect the button's state. If the button's + * state is the same as it was before, then we ignore this as noise. + */ + if(button_state == BUTTON_HAL_STATE_PRESSED && expired) { + /* + * Button is pressed and no tick counter running. Treat as new press. + * Include the debounce duration in the first periodic, so that the + * callback will happen 1 second after the button press, not 1 second + * after the end of the debounce. Notify process about the press event. + */ + button->press_duration_seconds = 0; + ctimer_set(&button->duration_ctimer, + CLOCK_SECOND - BUTTON_HAL_DEBOUNCE_DURATION, + duration_exceeded_callback, button); + process_post(PROCESS_BROADCAST, button_hal_press_event, button); + } else if(button_state == BUTTON_HAL_STATE_RELEASED && expired == 0) { + /* + * Button is released and there is a duration_ctimer running. Treat this + * as a new release and notify processes. + */ + ctimer_stop(&button->duration_ctimer); + process_post(PROCESS_BROADCAST, button_hal_release_event, button); + } +} +/*---------------------------------------------------------------------------*/ +static void +press_release_handler(gpio_hal_pin_mask_t pin_mask) +{ + pmask |= pin_mask; + process_poll(&button_hal_process); +} +/*---------------------------------------------------------------------------*/ +button_hal_button_t * +button_hal_get_by_id(uint8_t unique_id) +{ + button_hal_button_t **button; + + for(button = button_hal_buttons; *button != NULL; button++) { + if((*button)->unique_id == unique_id) { + return *button; + } + } + + return NULL; +} +/*---------------------------------------------------------------------------*/ +button_hal_button_t * +button_hal_get_by_index(uint8_t index) +{ + if(index >= button_hal_button_count) { + return NULL; + } + + return button_hal_buttons[index]; +} +/*---------------------------------------------------------------------------*/ +uint8_t +button_hal_get_state(button_hal_button_t *button) +{ + uint8_t pin_state = gpio_hal_arch_read_pin(button->pin); + + if((pin_state == 0 && button->negative_logic == true) || + (pin_state == 1 && button->negative_logic == false)) { + return BUTTON_HAL_STATE_PRESSED; + } + + return BUTTON_HAL_STATE_RELEASED; +} +/*---------------------------------------------------------------------------*/ +void +button_hal_init() +{ + button_hal_button_t **button; + gpio_hal_pin_cfg_t cfg; + + button_hal_press_event = process_alloc_event(); + button_hal_release_event = process_alloc_event(); + button_hal_periodic_event = process_alloc_event(); + + button_event_handler.pin_mask = 0; + button_event_handler.handler = press_release_handler; + + for(button = button_hal_buttons; *button != NULL; button++) { + cfg = GPIO_HAL_PIN_CFG_EDGE_BOTH | GPIO_HAL_PIN_CFG_INT_ENABLE | + (*button)->pull; + gpio_hal_arch_pin_set_input((*button)->pin); + gpio_hal_arch_pin_cfg_set((*button)->pin, cfg); + gpio_hal_arch_interrupt_enable((*button)->pin); + button_event_handler.pin_mask |= gpio_hal_pin_to_mask((*button)->pin); + } + + process_start(&button_hal_process, NULL); + + gpio_hal_register_handler(&button_event_handler); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(button_hal_process, ev, data) +{ + int_master_status_t status; + gpio_hal_pin_mask_t pins; + button_hal_button_t **button; + + PROCESS_BEGIN(); + + while(1) { + PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL); + + status = critical_enter(); + pins = pmask; + pmask = 0; + critical_exit(status); + + for(button = button_hal_buttons; *button != NULL; button++) { + if(gpio_hal_pin_to_mask((*button)->pin) & pins) { + /* Ignore all button presses/releases during its debounce */ + if(ctimer_expired(&(*button)->debounce_ctimer)) { + /* + * Here we merely set a debounce timer. At the end of the debounce we + * will inspect the button's state and we will take action only if it + * has changed. + * + * This is to prevent erroneous edge detections due to interference. + */ + ctimer_set(&(*button)->debounce_ctimer, BUTTON_HAL_DEBOUNCE_DURATION, + debounce_handler, *button); + } + } + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/dev/button-hal.h b/os/dev/button-hal.h new file mode 100644 index 0000000000000000000000000000000000000000..c1822ff8eb276a1b3c035511d22891dc3a52c343 --- /dev/null +++ b/os/dev/button-hal.h @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup dev + * @{ + */ +/*---------------------------------------------------------------------------*/ +/** + * \defgroup button_hal Button HAL + * + * Hardware abstraction layer for user buttons. + * + * This HAL enables an abstraction of general-purpose / user buttons or + * similar peripherals (e.g. a reed relay can also be abstracted through this + * HAL). The HAL handles software debounce timers internally, therefore the + * platform-specific button driver does not need to worry about debouncing. + * + * The platform developer needs to define a variable of type + * \c button_hal_button_t for each user button. Within this variable, the + * developer needs to specify the GPIO pin where the button is attached, + * whether the button uses negative logic, and whether the GPIO pin should + * be configured with internal pullup/down. The developer also needs to provide + * a unique index for each button, as well as a description. + * + * With those in place, the HAL will generate the following process events: + * + * - button_hal_press_event: Upon press of the button + * - button_hal_release_event: Upon release of the button + * - button_hal_periodic_event: Generated every second that the user button is + * kept pressed. + * + * With those events in place, an application can perform an action: + * + * - Immediately after the button gets pressed. + * - After the button has been pressed for N seconds. + * - Immediately upon release of the button. This action can vary depending + * on how long the button had been pressed for. + * + * A platform with user buttons can either implement this API (recommended) or + * the older button_sensor API. Some examples will not work if this API is not + * implemented. + * + * This API requires the platform to first support the GPIO HAL API. + * @{ + * + * \file + * Header file for the button HAL + */ +/*---------------------------------------------------------------------------*/ +#ifndef BUTTON_HAL_H_ +#define BUTTON_HAL_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +#include "sys/clock.h" +#include "sys/ctimer.h" + +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +/*---------------------------------------------------------------------------*/ +/** + * \brief Controls the software debounce timer duration. + * + * The platform can provide a more suitable value. This value will apply to + * all buttons. + */ +#ifdef BUTTON_HAL_CONF_DEBOUNCE_DURATION +#define BUTTON_HAL_DEBOUNCE_DURATION BUTTON_HAL_CONF_DEBOUNCE_DURATION +#else +#define BUTTON_HAL_DEBOUNCE_DURATION (CLOCK_SECOND >> 6) +#endif +/*---------------------------------------------------------------------------*/ +/** + * \brief Controls whether buttons will have human-readable names + * + * Define this to zero to save code space + */ +#if BUTTON_HAL_CONF_WITH_DESCRIPTION +#define BUTTON_HAL_WITH_DESCRIPTION BUTTON_HAL_CONF_WITH_DESCRIPTION +#else +#define BUTTON_HAL_WITH_DESCRIPTION 1 +#endif +/*---------------------------------------------------------------------------*/ +#define BUTTON_HAL_STATE_RELEASED 0 +#define BUTTON_HAL_STATE_PRESSED 1 +/*---------------------------------------------------------------------------*/ +/** + * Optional button IDs + */ +#define BUTTON_HAL_ID_BUTTON_ZERO 0x00 +#define BUTTON_HAL_ID_BUTTON_ONE 0x01 +#define BUTTON_HAL_ID_BUTTON_TWO 0x02 +#define BUTTON_HAL_ID_BUTTON_THREE 0x03 +#define BUTTON_HAL_ID_BUTTON_FOUR 0x04 +#define BUTTON_HAL_ID_BUTTON_FIVE 0x05 + +#define BUTTON_HAL_ID_USER_BUTTON BUTTON_HAL_ID_BUTTON_ZERO +/*---------------------------------------------------------------------------*/ +/** + * \brief A logical representation of a user button + */ +typedef struct button_hal_button_s button_hal_button_t; + +struct button_hal_button_s { + /** Used by the s/w debounce functionality */ + struct ctimer debounce_ctimer; + + /** A callback timer used to count duration of button presses */ + struct ctimer duration_ctimer; + +#if BUTTON_HAL_WITH_DESCRIPTION + /** + * \brief A textual description of the button + * + * This field may only be accessed using the BUTTON_HAL_GET_DESCRIPTION() + * macro. + */ + const char *description; +#endif + + /** True if the button uses negative logic (active: low) */ + const bool negative_logic; + + /** The gpio pin connected to the button */ + const gpio_hal_pin_t pin; + + /** The pin's pull configuration */ + const gpio_hal_pin_cfg_t pull; + + /** A counter of the duration (in seconds) of a button press */ + uint8_t press_duration_seconds; + + /** + * \brief A unique identifier for this button. + * + * The platform code is responsible of setting unique values here. This can + * be used later to determine which button generated an event. Many examples + * assume the existence of a button with ID == BUTTON_HAL_ID_BUTTON_ZERO, + * so it is good idea to use this ID for one of your platform's buttons. + */ + const uint8_t unique_id; +}; +/*---------------------------------------------------------------------------*/ +#if BUTTON_HAL_WITH_DESCRIPTION +/** + * \brief Define a button to be used by the HAL + * \param name The variable name for the button + * \param descr A textual description + * \param p The pin connected to the button + * \param nl True if the button is connected using negative logic + * \param u The button's pull configuration + * \param id A unique numeric identifier + */ +#define BUTTON_HAL_BUTTON(name, descr, p, u, id, nl) \ + static button_hal_button_t name = { \ + .description = descr, \ + .pin = p, \ + .pull = u, \ + .unique_id = id, \ + .negative_logic = nl, \ + } + +/** + * \brief Retrieve the textual description of a button + * \param b A pointer to the button button_hal_button_t + * + * This macro will return the value of the description field for b. If + * BUTTON_HAL_WITH_DESCRIPTION is 0 then this macro will return "" + */ +#define BUTTON_HAL_GET_DESCRIPTION(b) (b)->description +#else +#define BUTTON_HAL_BUTTON(name, descr, p, u, id, nl) \ + static button_hal_button_t name = { \ + .pin = p, \ + .pull = u, \ + .unique_id = id, \ + .negative_logic = nl, \ + } + +#define BUTTON_HAL_GET_DESCRIPTION(b) "" +#endif +/*---------------------------------------------------------------------------*/ +#define BUTTON_HAL_BUTTONS(...) \ + button_hal_button_t *button_hal_buttons[] = {__VA_ARGS__, NULL}; \ + const uint8_t button_hal_button_count = \ + (sizeof(button_hal_buttons) / sizeof(button_hal_buttons[0])) - 1; +/*---------------------------------------------------------------------------*/ +/** + * \brief The number of buttons on a device + */ +extern const uint8_t button_hal_button_count; +/*---------------------------------------------------------------------------*/ +/** + * \brief A broadcast event generated when a button gets pressed + */ +extern process_event_t button_hal_press_event; + +/** + * \brief A broadcast event generated when a button gets released + */ +extern process_event_t button_hal_release_event; + +/** + * \brief A broadcast event generated every second while a button is kept pressed + */ +extern process_event_t button_hal_periodic_event; +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialise the button HAL + */ +void button_hal_init(void); + +/** + * \brief Retrieve a button by ID + * \param unique_id The button unique ID to search for + * \return A pointer to the button or NULL if not found + */ +button_hal_button_t *button_hal_get_by_id(uint8_t unique_id); + +/** + * \brief Retrieve a button by its index + * \param index The button's index (0, 1, ... button_hal_button_count - 1) + * \return A pointer to the button or NULL if not found + */ +button_hal_button_t *button_hal_get_by_index(uint8_t index); + +/** + * \brief Get the state of a button (pressed / released) + * \param button A pointer to the button + * \retval BUTTON_HAL_STATE_RELEASED The button is currently released + * \retval BUTTON_HAL_STATE_PRESSED The button is currently pressed + */ +uint8_t button_hal_get_state(button_hal_button_t *button); +/*---------------------------------------------------------------------------*/ +#endif /* BUTTON_HAL_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/os/dev/gpio-hal.c b/os/dev/gpio-hal.c new file mode 100644 index 0000000000000000000000000000000000000000..6581522935eb66ed7f21bdb4faeb3d7c3553b3ea --- /dev/null +++ b/os/dev/gpio-hal.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup gpio-hal + * @{ + * + * \file + * Implementation of the platform-independent aspects of the GPIO HAL + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" +#include "lib/list.h" +#include "sys/log.h" + +#include <stdint.h> +#include <string.h> +/*---------------------------------------------------------------------------*/ +/* Log configuration */ +#define LOG_MODULE "GPIO HAL" +#define LOG_LEVEL LOG_LEVEL_NONE +/*---------------------------------------------------------------------------*/ +LIST(handlers); +/*---------------------------------------------------------------------------*/ +void +gpio_hal_register_handler(gpio_hal_event_handler_t *handler) +{ + list_add(handlers, handler); +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_event_handler(gpio_hal_pin_mask_t pins) +{ + gpio_hal_event_handler_t *this; + + for(this = list_head(handlers); this != NULL; this = this->next) { + if(pins & this->pin_mask) { + if(this->handler != NULL) { + this->handler(pins & this->pin_mask); + } + } + } +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_init() +{ + list_init(handlers); +} +/*---------------------------------------------------------------------------*/ +#if GPIO_HAL_ARCH_SW_TOGGLE +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_toggle_pin(gpio_hal_pin_t pin) +{ + if(pin >= GPIO_HAL_PIN_COUNT) { + LOG_ERR("Pin %u out of bounds\n", pin); + return; + } + + gpio_hal_arch_write_pin(pin, gpio_hal_arch_read_pin(pin) ^ 1); +} +/*---------------------------------------------------------------------------*/ +void +gpio_hal_arch_toggle_pins(gpio_hal_pin_mask_t pins) +{ + gpio_hal_arch_write_pins(pins, ~gpio_hal_arch_read_pins(pins)); +} +/*---------------------------------------------------------------------------*/ +#endif /* GPIO_HAL_ARCH_SW_TOGGLE */ +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/os/dev/gpio-hal.h b/os/dev/gpio-hal.h new file mode 100644 index 0000000000000000000000000000000000000000..b6af7bf74c29f4bc9b30bf6a111605d6f50e4872 --- /dev/null +++ b/os/dev/gpio-hal.h @@ -0,0 +1,502 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup dev + * @{ + * + * \defgroup gpio-hal GPIO Hardware Abstraction Layer + * + * The GPIO HAL provides a set of common functions that can be used in a + * platform-independent fashion. + * + * Internally, the GPIO HAL handles edge detection handling and also provides + * fallback functions for GPIO pin toggling if the hardware does not have + * a direct method of toggling pins through direct register access. + * + * @{ + * + * \file + * Header file for the GPIO HAL + */ +/*---------------------------------------------------------------------------*/ +#ifndef GPIO_HAL_H_ +#define GPIO_HAL_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include <stdint.h> +/*---------------------------------------------------------------------------*/ +/** + * \brief Specifies whether software-based pin toggle is required + * + * Some MCUs allow GPIO pin toggling via direct register access. For these + * MCUs, define GPIO_HAL_CONF_ARCH_SW_TOGGLE to 0 and then implement + * gpio_hal_arch_toggle_pin() and gpio_hal_arch_toggle_pins() + * + * \sa gpio_hal_arch_toggle_pin() + * \sa gpio_hal_arch_toggle_pins() + */ +#ifdef GPIO_HAL_CONF_ARCH_SW_TOGGLE +#define GPIO_HAL_ARCH_SW_TOGGLE GPIO_HAL_CONF_ARCH_SW_TOGGLE +#else +#define GPIO_HAL_ARCH_SW_TOGGLE 1 +#endif +/*---------------------------------------------------------------------------*/ +/** + * \brief GPIO pin number representation + */ +typedef uint8_t gpio_hal_pin_t; + +/** + * \brief GPIO pin configuration + * + * A logical representation of a pin's configuration. It is an OR combination + * of GPIO_HAL_PIN_CFG_xyz macros. + */ +typedef uint8_t gpio_hal_pin_cfg_t; + +#ifdef GPIO_HAL_CONF_PIN_COUNT +#define GPIO_HAL_PIN_COUNT GPIO_HAL_CONF_PIN_COUNT +#else +#define GPIO_HAL_PIN_COUNT 32 +#endif + +#if GPIO_HAL_PIN_COUNT > 32 +typedef uint64_t gpio_hal_pin_mask_t; +#else +/** + * \brief GPIO pin mask representation + */ +typedef uint32_t gpio_hal_pin_mask_t; +#endif + +typedef void (*gpio_hal_callback_t)(gpio_hal_pin_mask_t pin_mask); +/*---------------------------------------------------------------------------*/ +#define GPIO_HAL_PIN_CFG_PULL_NONE 0x00 +#define GPIO_HAL_PIN_CFG_PULL_UP 0x01 +#define GPIO_HAL_PIN_CFG_PULL_DOWN 0x02 +#define GPIO_HAL_PIN_CFG_PULL_MASK (GPIO_HAL_PIN_CFG_PULL_UP | \ + GPIO_HAL_PIN_CFG_PULL_DOWN) + +#define GPIO_HAL_PIN_CFG_EDGE_NONE 0x00 +#define GPIO_HAL_PIN_CFG_EDGE_RISING 0x04 +#define GPIO_HAL_PIN_CFG_EDGE_FALLING 0x08 +#define GPIO_HAL_PIN_CFG_EDGE_BOTH (GPIO_HAL_PIN_CFG_EDGE_RISING | \ + GPIO_HAL_PIN_CFG_EDGE_FALLING) + +#define GPIO_HAL_PIN_CFG_INT_DISABLE 0x00 +#define GPIO_HAL_PIN_CFG_INT_ENABLE 0x80 +#define GPIO_HAL_PIN_CFG_INT_MASK 0x80 +/*---------------------------------------------------------------------------*/ +/** + * \brief Datatype for GPIO event handlers + * + * A GPIO event handler is a function that gets called whenever a pin triggers + * an event. The same handler can be registered to handle events for more than + * one pin by setting the respective pin's position but in \e pin_mask. + */ +typedef struct gpio_hal_event_handler_s { + struct gpio_hal_event_handler_s *next; + gpio_hal_callback_t handler; + gpio_hal_pin_mask_t pin_mask; +} gpio_hal_event_handler_t; +/*---------------------------------------------------------------------------*/ +/** + * \brief Unknown GPIO + * + * A default GPIO value for unknown GPIO + */ +#define GPIO_HAL_PIN_UNKNOWN 0xFF +/*---------------------------------------------------------------------------*/ +/** + * \name Core GPIO functions + * + * Functions implemented by the HAL itself + * @{ + */ +/** + * \brief Initialise the GPIO HAL + */ +void gpio_hal_init(void); + +/** + * \brief Register a function to be called whenever a pin triggers an event + * \param handler The handler representation + * + * The handler must be pre-allocated statically by the caller. + * + * This function can be used to register a function to be called by the HAL + * whenever a GPIO interrupt occurs. + * + * \sa gpio_hal_event_handler + */ +void gpio_hal_register_handler(gpio_hal_event_handler_t *handler); + +/** + * \brief The platform-independent GPIO event handler + * \param pins OR mask of pins that generated an event + * + * Whenever a GPIO input interrupt occurs (edge or level detection) and an ISR + * is triggered, the ISR must call this function, passing as argument an ORd + * mask of the pins that triggered the interrupt. This function will then + * call the registered event handlers (if any) for the pins that triggered the + * event. The platform code should make no assumptions as to the order that + * the handlers will be called. + * + * If a pin set in the mask has an event handler registered, this function + * will call the registered handler. + * + * This function will not clear any CPU interrupt flags, this should be done + * by the calling ISR. + * + * \sa gpio_hal_register_handler + */ +void gpio_hal_event_handler(gpio_hal_pin_mask_t pins); + +/** + * \brief Convert a pin to a pin mask + * \param pin The pin + * \return The corresponding mask + */ +#define gpio_hal_pin_to_mask(pin) (1 << (pin)) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Functions to be provided by the platform + * + * All the functions below must be provided by the platform's developer. The + * HAL offers the developer a number of options of how to provide the required + * functionality. + * + * - The developer can provide a symbol. For example, the developer can create + * a .c file and implement a function called gpio_hal_arch_set_pin() + * - The developer can provide a function-like macro that has the same name as + * the function declared here. In this scenario, the declaration here will + * be removed by the pre-processor. For example, the developer can do + * something like: + * + * \code + * #define gpio_hal_arch_write_pin(p, v) platform_sdk_function(p, v) + * \endcode + * + * - The developer can provide a static inline implementation. For this to + * work, the developer can do something like: + * + * \code + * #define gpio_hal_arch_set_pin(p) set_pin(p) + * static inline void set_pin(gpio_hal_pin_t pin) { ... } + * \endcode + * + * In the latter two cases, the developer will likely provide implementations + * in a header file. In this scenario, one of the platform's configuration + * files must define GPIO_HAL_CONF_ARCH_HDR_PATH to the name of this header + * file. For example: + * + * \code + * #define GPIO_HAL_CONF_ARCH_HDR_PATH "dev/gpio-hal-arch.h" + * \endcode + * + * @{ + */ +/*---------------------------------------------------------------------------*/ +/* Include Arch-Specific conf */ +#ifdef GPIO_HAL_CONF_ARCH_HDR_PATH +#include GPIO_HAL_CONF_ARCH_HDR_PATH +#endif /* GPIO_HAL_CONF_ARCH_HDR_PATH */ +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_interrupt_enable +/** + * \brief Enable interrupts for a gpio pin + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_interrupt_enable(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_interrupt_disable +/** + * \brief Disable interrupts for a gpio pin + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_interrupt_disable(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_pin_cfg_set +/** + * \brief Configure a gpio pin + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * \param cfg The configuration + * + * \e cfg is an OR mask of GPIO_HAL_PIN_CFG_xyz + * + * The implementation of this function also has to make sure that \e pin is + * configured as software-controlled GPIO. + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_pin_cfg_get +/** + * \brief Read the configuration of a GPIO pin + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * \return An OR mask of GPIO_HAL_PIN_CFG_xyz + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +gpio_hal_pin_cfg_t gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_pin_set_input +/** + * \brief Configure a pin as GPIO input + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * + * The implementation of this function also has to make sure that \e pin is + * configured as software-controlled GPIO. + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_pin_set_input(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_pin_set_output +/** + * \brief Configure a pin as GPIO output + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * + * The implementation of this function also has to make sure that \e pin is + * configured as software-controlled GPIO. + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_pin_set_output(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_set_pin +/** + * \brief Set a GPIO pin to logical high + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_set_pin(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_clear_pin +/** + * \brief Clear a GPIO pin (logical low) + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_clear_pin(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_toggle_pin +/** + * \brief Toggle a GPIO pin + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * + * Some MCUs allow GPIO pin toggling directly via register access. In this + * case, it is a good idea to provide an implementation of this function. + * However, a default, software-based implementation is also provided by the + * HAL and can be used if the MCU does not have a pin toggle register. To use + * the HAL function, define GPIO_HAL_ARCH_SW_TOGGLE as 1. To provide your own + * implementation, define GPIO_HAL_ARCH_SW_TOGGLE as 0. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_toggle_pin(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_read_pin +/** + * \brief Read a GPIO pin + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * \retval 0 The pin is logical low + * \retval 1 The pin is logical high + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +uint8_t gpio_hal_arch_read_pin(gpio_hal_pin_t pin); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_write_pin +/** + * \brief Write a GPIO pin + * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1) + * \param value 0: Logical low; 1: Logical high + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_write_pin(gpio_hal_pin_t pin, uint8_t value); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_set_pins +/** + * \brief Set multiple pins to logical high + * \param pins An ORd pin mask of the pins to set + * + * A pin will be set to logical high if its position in \e pins is set. For + * example you can set pins 0 and 3 by passing 0x09. + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_set_pins(gpio_hal_pin_mask_t pins); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_clear_pins +/** + * \brief Clear multiple pins to logical low + * \param pins An ORd pin mask of the pins to clear + * + * A pin will be set to logical low if its position in \e pins is set. For + * example you can clear pins 0 and 3 by passing 0x09. + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_clear_pins(gpio_hal_pin_mask_t pins); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_toggle_pins +/** + * \brief Toggle multiple pins + * \param pins An ORd pin mask of the pins to toggle + * + * A pin will be toggled if its position in \e pins is set. For example you + * can toggle pins 0 and 3 by passing 0x09. + * + * Some MCUs allow GPIO pin toggling directly via register access. In this + * case, it is a good idea to provide an implementation of this function. + * However, a default, software-based implementation is also provided by the + * HAL and can be used if the MCU does not have a pin toggle register. To use + * the HAL function, define GPIO_HAL_ARCH_SW_TOGGLE as 1. To provide your own + * implementation, define GPIO_HAL_ARCH_SW_TOGGLE as 0. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_toggle_pins(gpio_hal_pin_mask_t pins); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_read_pins +/** + * \brief Read multiple pins + * \param pins An ORd pin mask of the pins to read + * \retval An ORd mask of the pins that are high + * + * If the position of the pin in \e pins is set and the pin is logical high + * then the position of the pin in the return value will be set. For example, + * if you pass 0x09 as the value of \e pins and the return value is 0x08 then + * pin 3 is logical high and pin 0 is logical low. + * + * It is the platform developer's responsibility to provide an implementation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +gpio_hal_pin_mask_t gpio_hal_arch_read_pins(gpio_hal_pin_mask_t pins); +#endif +/*---------------------------------------------------------------------------*/ +#ifndef gpio_hal_arch_write_pins +/** + * \brief Write multiple pins + * \param pins An ORd pin mask of the pins to write + * \param value An ORd mask of the value to write + * + * The function will modify GPIO pins that have their position in the mask set. + * pins, the function will write the value specified in the corresponding + * position in \e value. + + * For example, you can set pin 3 and clear pin 0 by a single call to this + * function. To achieve this, \e pins must be 0x09 and \e value 0x08. + * + * It is the platform developer's responsibility to provide an implementation. + * + * There is no guarantee that this function will result in an atomic operation. + * + * The implementation can be provided as a global symbol, an inline function + * or a function-like macro, as described above. + */ +void gpio_hal_arch_write_pins(gpio_hal_pin_mask_t pins, + gpio_hal_pin_mask_t value); +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +#endif /* GPIO_HAL_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/os/dev/leds.c b/os/dev/leds.c index 9273ad9ca3338c13215508154688db8e1d66555c..f2ce82c29229b9eb659d645c5a5d3dfac46d532e 100644 --- a/os/dev/leds.c +++ b/os/dev/leds.c @@ -1,51 +1,56 @@ /* * Copyright (c) 2005, Swedish Institute of Computer Science + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. * - * This file is part of the Contiki operating system. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup leds + * @{ * + * \file + * Implementation of the platform-independent aspects of the LED HAL */ - +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio-hal.h" #include "dev/leds.h" -#include "sys/clock.h" -static unsigned char leds; +#include <stdint.h> +#include <stdbool.h> /*---------------------------------------------------------------------------*/ -static inline void -show_leds(unsigned char new_leds) -{ - leds_arch_set(new_leds); -} +#if LEDS_LEGACY_API /*---------------------------------------------------------------------------*/ void leds_init(void) { leds_arch_init(); - leds = 0; } /*---------------------------------------------------------------------------*/ void @@ -53,7 +58,7 @@ leds_blink(void) { /* Blink all leds that were initially off. */ unsigned char blink; - blink = ~leds; + blink = ~leds_arch_get(); leds_toggle(blink); clock_delay(400); @@ -67,26 +72,158 @@ leds_get(void) { } /*---------------------------------------------------------------------------*/ void -leds_set(unsigned char ledv) +leds_set(leds_mask_t ledv) { - show_leds(ledv); + leds_arch_set(ledv); } /*---------------------------------------------------------------------------*/ void -leds_on(unsigned char ledv) +leds_on(leds_mask_t ledv) { - show_leds(leds | ledv); + leds_arch_set(leds_arch_get() | ledv); } /*---------------------------------------------------------------------------*/ void -leds_off(unsigned char ledv) +leds_off(leds_mask_t ledv) { - show_leds(leds & ~ledv); + leds_arch_set(leds_arch_get() & ~ledv); } /*---------------------------------------------------------------------------*/ void -leds_toggle(unsigned char ledv) +leds_toggle(leds_mask_t ledv) { - show_leds(leds ^ ledv); + leds_arch_set(leds_arch_get() ^ ledv); +} +/*---------------------------------------------------------------------------*/ +#else /* LEDS_LEGACY_API */ +/*---------------------------------------------------------------------------*/ +#if LEDS_COUNT +extern const leds_t leds_arch_leds[]; +#else +static const leds_t *leds_arch_leds = NULL; +#endif +/*---------------------------------------------------------------------------*/ +void +leds_init() +{ + leds_num_t led; + + for(led = 0; led < LEDS_COUNT; led++) { + gpio_hal_arch_pin_set_output(leds_arch_leds[led].pin); + } + leds_off(LEDS_ALL); } /*---------------------------------------------------------------------------*/ +void +leds_single_on(leds_num_t led) +{ + if(led >= LEDS_COUNT) { + return; + } + + if(leds_arch_leds[led].negative_logic) { + gpio_hal_arch_clear_pin(leds_arch_leds[led].pin); + } else { + gpio_hal_arch_set_pin(leds_arch_leds[led].pin); + } +} +/*---------------------------------------------------------------------------*/ +void +leds_single_off(leds_num_t led) +{ + if(led >= LEDS_COUNT) { + return; + } + + if(leds_arch_leds[led].negative_logic) { + gpio_hal_arch_set_pin(leds_arch_leds[led].pin); + } else { + gpio_hal_arch_clear_pin(leds_arch_leds[led].pin); + } +} +/*---------------------------------------------------------------------------*/ +void +leds_single_toggle(leds_num_t led) +{ + if(led >= LEDS_COUNT) { + return; + } + + gpio_hal_arch_toggle_pin(leds_arch_leds[led].pin); +} +/*---------------------------------------------------------------------------*/ +void +leds_on(leds_mask_t leds) +{ + leds_num_t led; + + for(led = 0; led < LEDS_COUNT; led++) { + if((1 << led) & leds) { + if(leds_arch_leds[led].negative_logic) { + gpio_hal_arch_clear_pin(leds_arch_leds[led].pin); + } else { + gpio_hal_arch_set_pin(leds_arch_leds[led].pin); + } + } + } +} +/*---------------------------------------------------------------------------*/ +void +leds_off(leds_mask_t leds) +{ + leds_num_t led; + + for(led = 0; led < LEDS_COUNT; led++) { + if((1 << led) & leds) { + if(leds_arch_leds[led].negative_logic) { + gpio_hal_arch_set_pin(leds_arch_leds[led].pin); + } else { + gpio_hal_arch_clear_pin(leds_arch_leds[led].pin); + } + } + } +} +/*---------------------------------------------------------------------------*/ +void +leds_toggle(leds_mask_t leds) +{ + leds_num_t led; + + for(led = 0; led < LEDS_COUNT; led++) { + if((1 << led) & leds) { + gpio_hal_arch_toggle_pin(leds_arch_leds[led].pin); + } + } +} +/*---------------------------------------------------------------------------*/ +void +leds_set(leds_mask_t leds) +{ + leds_off(LEDS_ALL); + leds_on(leds); +} +/*---------------------------------------------------------------------------*/ +leds_mask_t +leds_get() +{ + leds_mask_t rv = 0; + leds_num_t led; + uint8_t pin_state; + + for(led = 0; led < LEDS_COUNT; led++) { + pin_state = gpio_hal_arch_read_pin(leds_arch_leds[led].pin); + + if((leds_arch_leds[led].negative_logic == false && pin_state == 1) || + (leds_arch_leds[led].negative_logic == true && pin_state == 0)) { + rv |= 1 << led; + } + } + + return rv; +} +/*---------------------------------------------------------------------------*/ +#endif /* LEDS_LEGACY_API */ +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/os/dev/leds.h b/os/dev/leds.h index d99fb8196fa9f471e5ecac37a2fec3f61caf32cc..654ed250eee09af5e8873954a5cb52b3c901556e 100644 --- a/os/dev/leds.h +++ b/os/dev/leds.h @@ -1,98 +1,329 @@ /* * Copyright (c) 2005, Swedish Institute of Computer Science + * Copyright (c) 2018, George Oikonomou - http://www.spd.gr * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. */ +/*---------------------------------------------------------------------------*/ /** * \addtogroup dev * @{ */ - +/*---------------------------------------------------------------------------*/ /** - * \defgroup leds LEDs API + * \defgroup leds LED Hardware Abstraction Layer + * + * The LED HAL provides a set of functions that can manipulate LEDS. + * + * Currently, the LED HAL supports two APIs: + * + * - The new, platform-independent API (recommended for all new platforms). + * - The legacy API (supported until all existing platforms have been ported + * to support the new API). + * + * The two APIs use very similar semantics and have an overlapping set of + * function calls. This is done so that platform-independent examples can + * work on all platforms, irrespective of which API each platform supports. + * + * The legacy API can be enabled by the platform code by defining + * LEDS_CONF_LEGACY_API 1. + * + * Once all platforms supported in contiki-ng/contiki-ng have been ported to + * the new API, the legacy API will be deleted without warning. For this + * reason, it is strongly recommended to use the new API for new platforms and + * for platforms hosted in external repositories. + * + * The new API provides a set of common LED manipulation functions that can be + * used in a platform-independent fashion. Functions exist to manipulate one + * LED at a time (\c leds_single_XYZ), as well as to manipulate multiple LEDs + * at a time (\c leds_XYZ). * - * The LEDs API defines a set of functions for accessing LEDs for - * Contiki plaforms with LEDs. + * The assumption is that each LED is connected to a GPIO pin using either + * positive or negative logic. * - * A platform with LED support must implement this API. + * LEDs on a device are numbered incrementally, starting from 0 and counting + * upwards. Thus, if a device has 3 LEDs they will be numbered 0, 1 and 2. + * Convenience macros (LEDS_LED_n) are provided to refer to LEDs. These macros + * can be used as arguments to functions that manipulate a single LED, such + * as leds_single_on() but \e not leds_on(). + * + * The legacy scheme that uses colours to refer to LEDs is maintained, without + * semantic changes, but with minor changes in logic: + * + * - Firstly, we now define 5 LED colours: Red, Green, Blue, Yellow, Orange. + * These are sufficient to cover all currently-supported platforms. + * - Secondly, unless a platform specifies that a LED of a specific colour + * exists, the HAL will assume that it does not. + * - Trying to manipulate a non-existent LED will not cause build errors, but + * will not cause any changes to LED state either. + * - We no longer map non-existing LED colours to existing ones. + * + * Note that, in order to avoid changes to LED colour semantics between the + * two APIs, references to LED by colour are bitwise OR masks and should + * therefore only be used as argument to functions that manipulate multiple + * LEDS (e.g. leds_off() and \e not leds_single_off()). + * + * In terms of porting for new platforms, developers simply have to: + * + * - Define variables of type leds_t to represent their platform's LEDs + * - Specify the number of LEDs on their device by defining LEDS_CONF_COUNT + * - Map red colours to numbers (e.g. \#define LEDS_CONF_RED 1) + * + * \file + * Header file for the LED HAL * @{ */ - +/*---------------------------------------------------------------------------*/ #ifndef LEDS_H_ #define LEDS_H_ - -/* Allow platform to override LED numbering */ +/*---------------------------------------------------------------------------*/ #include "contiki.h" +#include "dev/gpio-hal.h" -void leds_init(void); - +#include <stdint.h> +#include <stdbool.h> +/*---------------------------------------------------------------------------*/ +#if LEDS_CONF_LEGACY_API /** - * Blink all LEDs. + * \brief Define to 1 to enabled the legacy LED API. */ -void leds_blink(void); +#define LEDS_LEGACY_API LEDS_CONF_LEGACY_API +#else +#define LEDS_LEGACY_API 0 +#endif +/*---------------------------------------------------------------------------*/ +/** + * \brief A default LED colour for non-existing LEDs + */ +#define LEDS_COLOUR_NONE 0x00 +/*---------------------------------------------------------------------------*/ +/* LED colour to number mappings. Applicable to both APIs */ +#ifdef LEDS_CONF_RED +#define LEDS_RED LEDS_CONF_RED +#else +#define LEDS_RED LEDS_COLOUR_NONE +#endif -#ifndef LEDS_GREEN -#define LEDS_GREEN 1 -#endif /* LEDS_GREEN */ -#ifndef LEDS_YELLOW -#define LEDS_YELLOW 2 -#endif /* LEDS_YELLOW */ -#ifndef LEDS_RED -#define LEDS_RED 4 -#endif /* LEDS_RED */ -#ifndef LEDS_BLUE -#define LEDS_BLUE LEDS_YELLOW -#endif /* LEDS_BLUE */ +#ifdef LEDS_CONF_GREEN +#define LEDS_GREEN LEDS_CONF_GREEN +#else +#define LEDS_GREEN LEDS_COLOUR_NONE +#endif +#ifdef LEDS_CONF_BLUE +#define LEDS_BLUE LEDS_CONF_BLUE +#else +#define LEDS_BLUE LEDS_COLOUR_NONE +#endif + +#ifdef LEDS_CONF_YELLOW +#define LEDS_YELLOW LEDS_CONF_YELLOW +#else +#define LEDS_YELLOW LEDS_COLOUR_NONE +#endif + +#ifdef LEDS_CONF_ORANGE +#define LEDS_ORANGE LEDS_CONF_ORANGE +#else +#define LEDS_ORANGE LEDS_COLOUR_NONE +#endif +/*---------------------------------------------------------------------------*/ +/** + * \brief The LED number + */ +typedef uint8_t leds_num_t; + +/** + * \brief An OR mask datatype to represents multiple LEDs. + */ +typedef uint8_t leds_mask_t; +/*---------------------------------------------------------------------------*/ +#if LEDS_LEGACY_API +/*---------------------------------------------------------------------------*/ #ifdef LEDS_CONF_ALL #define LEDS_ALL LEDS_CONF_ALL -#else /* LEDS_CONF_ALL */ +#else #define LEDS_ALL 7 -#endif /* LEDS_CONF_ALL */ +#endif +/*---------------------------------------------------------------------------*/ +void leds_blink(void); + +/* Legacy LED API arch-specific functions */ +void leds_arch_init(void); +leds_mask_t leds_arch_get(void); +void leds_arch_set(leds_mask_t leds); +/*---------------------------------------------------------------------------*/ +#else /* LEDS_LEGACY_API */ +/*---------------------------------------------------------------------------*/ +#ifdef LEDS_CONF_COUNT +#define LEDS_COUNT LEDS_CONF_COUNT +#else +/** + * \brief The number of LEDs present on a device + */ +#define LEDS_COUNT 0 +#endif +/*---------------------------------------------------------------------------*/ +/** + * \brief The OR mask representation of all device LEDs + */ +#define LEDS_ALL ((1 << LEDS_COUNT) - 1) +/*---------------------------------------------------------------------------*/ +#endif /* LEDS_LEGACY_API */ +/*---------------------------------------------------------------------------*/ +#define LEDS_LED1 0x00 /**< Convenience macro to refer to the 1st LED (LED 1) */ +#define LEDS_LED2 0x01 /**< Convenience macro to refer to the 2nd LED (LED 2) */ +#define LEDS_LED3 0x02 /**< Convenience macro to refer to the 3rd LED (LED 3) */ +#define LEDS_LED4 0x03 /**< Convenience macro to refer to the 4th LED (LED 4) */ +#define LEDS_LED5 0x04 /**< Convenience macro to refer to the 5th LED (LED 5) */ +/*---------------------------------------------------------------------------*/ +/** + * \brief A LED logical representation + * + * \e pin corresponds to the GPIO pin a LED is driven by, using GPIO HAL pin + * representation. + * + * \e negative_logic should be set to false if the LED is active low. + */ +typedef struct leds_s { + gpio_hal_pin_t pin; + bool negative_logic; +} leds_t; +/*---------------------------------------------------------------------------*/ +/** + * \brief Convert a LED number to a mask representation + * \param l The pin number (normally a variable of type leds_num_t) + * \return An OR mask of type leds_mask_t + */ +#define LEDS_NUM_TO_MASK(l) (1 << (l)) +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialise the LED HAL + * + * This function will set corresponding LED GPIO pins to output and will also + * set the initial state of all LEDs to off. + */ +void leds_init(void); /** - * Returns the current status of all leds + * \brief Turn a single LED on + * \param led The led + * + * The \e led argument should be the LED's number, in other words one of the + * LED_Ln macros. + * + * This function will not change the state of other LEDs. */ -unsigned char leds_get(void); -void leds_set(unsigned char leds); -void leds_on(unsigned char leds); -void leds_off(unsigned char leds); -void leds_toggle(unsigned char leds); +void leds_single_on(leds_num_t led); /** - * Leds implementation + * \brief Turn a single LED off + * \param led The led + * + * The \e led argument should be the LED's number, in other words one of the + * LED_Ln macros. + * + * This function will not change the state of other LEDs. */ -void leds_arch_init(void); -unsigned char leds_arch_get(void); -void leds_arch_set(unsigned char leds); +void leds_single_off(leds_num_t led); -#endif /* LEDS_H_ */ +/** + * \brief Toggle a single LED + * \param led The led + * + * The \e led argument should be the LED's number, in other words one of the + * LED_Ln macros. + * + * This function will not change the state of other LEDs. + */ +void leds_single_toggle(leds_num_t led); + +/** + * \brief Turn on multiple LEDs + * \param leds The leds to be turned on as an OR mask + * + * The \e led argument should be a bitwise mask of the LEDs to be changed. + * For example, to turn on LEDs 1 and 3, you should pass + * LED_NUM_TO_MASK(LED_L1) | LED_NUM_TO_MASK(LED_L3) = 1 | 4 = 5 + * + * This function will not change the state of other LEDs. + */ +void leds_on(leds_mask_t leds); -/** @} */ -/** @} */ +/** + * \brief Turn off multiple LEDs + * \param leds The leds to be turned off as an OR mask + * + * The \e led argument should be a bitwise mask of the LEDs to be changed. + * For example, to turn on LEDs 1 and 3, you should pass + * LED_NUM_TO_MASK(LED_L1) | LED_NUM_TO_MASK(LED_L3) = 1 | 4 = 5 + * + * This function will not change the state of other LEDs. + */ +void leds_off(leds_mask_t leds); + +/** + * \brief Toggle multiple LEDs + * \param leds The leds to be toggled as an OR mask + * + * The \e led argument should be a bitwise mask of the LEDs to be changed. + * For example, to turn on LEDs 1 and 3, you should pass + * LED_NUM_TO_MASK(LED_L1) | LED_NUM_TO_MASK(LED_L3) = 1 | 4 = 5 + * + * This function will not change the state of other LEDs. + */ +void leds_toggle(leds_mask_t leds); + +/** + * \brief Set all LEDs to a specific state + * \param leds The state of all LEDs afer this function returns + * + * The \e led argument should be a bitwise mask of the LEDs to be changed. + * For example, to turn on LEDs 1 and 3, you should pass + * LED_NUM_TO_MASK(LED_L1) | LED_NUM_TO_MASK(LED_L3) = 1 | 4 = 5 + * + * This function will change the state of all LEDs. LEDs not set in the \e leds + * mask will be turned off. + */ +void leds_set(leds_mask_t leds); + +/** + * \brief Get the status of LEDs + * \return A bitwise mask indicating whether each individual LED is on or off + * + * The return value is a bitwise mask. If a bit is set then the corresponding + * LED is on. + */ +leds_mask_t leds_get(void); +/*---------------------------------------------------------------------------*/ +#endif /* LEDS_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/os/dev/slip.c b/os/dev/slip.c index b27dca3327a457091c7e9257976d79a1566baf98..3cfe9ea078d06e379af7c1f1dd65ac44e7280a25 100644 --- a/os/dev/slip.c +++ b/os/dev/slip.c @@ -26,48 +26,41 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * */ - - -#include <stdio.h> -#include <string.h> - +/*---------------------------------------------------------------------------*/ #include "contiki.h" - #include "net/ipv6/uip.h" -#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) - #include "dev/slip.h" +#include <stdio.h> +#include <string.h> +/*---------------------------------------------------------------------------*/ #define SLIP_END 0300 #define SLIP_ESC 0333 #define SLIP_ESC_END 0334 #define SLIP_ESC_ESC 0335 - +/*---------------------------------------------------------------------------*/ PROCESS(slip_process, "SLIP driver"); - -uint8_t slip_active; - -#if 1 -#define SLIP_STATISTICS(statement) -#else -uint16_t slip_rubbish, slip_twopackets, slip_overflow, slip_ip_drop; +/*---------------------------------------------------------------------------*/ +static uint8_t slip_active; +/*---------------------------------------------------------------------------*/ +#if SLIP_CONF_WITH_STATS +static uint16_t slip_rubbish, slip_twopackets, slip_overflow, slip_ip_drop; #define SLIP_STATISTICS(statement) statement +#else +#define SLIP_STATISTICS(statement) #endif - +/*---------------------------------------------------------------------------*/ /* Must be at least one byte larger than UIP_BUFSIZE! */ #define RX_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN + 16) - +/*---------------------------------------------------------------------------*/ enum { - STATE_TWOPACKETS = 0, /* We have 2 packets and drop incoming data. */ + STATE_TWOPACKETS = 0, /* We have 2 packets and drop incoming data. */ STATE_OK = 1, STATE_ESC = 2, STATE_RUBBISH = 3, }; - +/*---------------------------------------------------------------------------*/ /* * Variables begin and end manage the buffer space in a cyclic * fashion. The first used byte is at begin and end is one byte past @@ -78,13 +71,12 @@ enum { * [pkt_end, end). If more bytes arrive in state STATE_TWOPACKETS * they are discarded. */ - static uint8_t state = STATE_TWOPACKETS; static uint16_t begin, next_free; static uint8_t rxbuf[RX_BUFSIZE]; -static uint16_t pkt_end; /* SLIP_END tracker. */ +static uint16_t pkt_end; /* SLIP_END tracker. */ -static void (* input_callback)(void) = NULL; +static void (*input_callback)(void) = NULL; /*---------------------------------------------------------------------------*/ void slip_set_input_callback(void (*c)(void)) @@ -92,36 +84,13 @@ slip_set_input_callback(void (*c)(void)) input_callback = c; } /*---------------------------------------------------------------------------*/ -/* slip_send: forward (IPv4) packets with {UIP_FW_NETIF(..., slip_send)} - * was used in slip-bridge.c - */ -uint8_t +void slip_send(void) { - uint16_t i; - uint8_t *ptr; - uint8_t c; - - slip_arch_writeb(SLIP_END); - - ptr = &uip_buf[UIP_LLH_LEN]; - for(i = 0; i < uip_len; ++i) { - c = *ptr++; - if(c == SLIP_END) { - slip_arch_writeb(SLIP_ESC); - c = SLIP_ESC_END; - } else if(c == SLIP_ESC) { - slip_arch_writeb(SLIP_ESC); - c = SLIP_ESC_ESC; - } - slip_arch_writeb(c); - } - slip_arch_writeb(SLIP_END); - - return UIP_FW_OK; + slip_write(&uip_buf[UIP_LLH_LEN], uip_len); } /*---------------------------------------------------------------------------*/ -uint8_t +void slip_write(const void *_ptr, int len) { const uint8_t *ptr = _ptr; @@ -141,9 +110,8 @@ slip_write(const void *_ptr, int len) } slip_arch_writeb(c); } - slip_arch_writeb(SLIP_END); - return len; + slip_arch_writeb(SLIP_END); } /*---------------------------------------------------------------------------*/ static void @@ -153,56 +121,9 @@ rxbuf_init(void) state = STATE_OK; } /*---------------------------------------------------------------------------*/ -/* Upper half does the polling. */ static uint16_t slip_poll_handler(uint8_t *outbuf, uint16_t blen) { -#ifdef SLIP_CONF_MICROSOFT_CHAT - /* This is a hack and won't work across buffer edge! */ - if(rxbuf[begin] == 'C') { - int i; - if(begin < next_free && (next_free - begin) >= 6 - && memcmp(&rxbuf[begin], "CLIENT", 6) == 0) { - state = STATE_TWOPACKETS; /* Interrupts do nothing. */ - memset(&rxbuf[begin], 0x0, 6); - - rxbuf_init(); - - for(i = 0; i < 13; i++) { - slip_arch_writeb("CLIENTSERVER\300"[i]); - } - return 0; - } - } -#endif /* SLIP_CONF_MICROSOFT_CHAT */ - -#ifdef SLIP_CONF_ANSWER_MAC_REQUEST - else if(rxbuf[begin] == '?') { - /* Used by tapslip6 to request mac for auto configure */ - int i, j; - char* hexchar = "0123456789abcdef"; - if(begin < next_free && (next_free - begin) >= 2 - && rxbuf[begin + 1] == 'M') { - state = STATE_TWOPACKETS; /* Interrupts do nothing. */ - rxbuf[begin] = 0; - rxbuf[begin + 1] = 0; - - rxbuf_init(); - - linkaddr_t addr = get_mac_addr(); - /* this is just a test so far... just to see if it works */ - slip_arch_writeb('!'); - slip_arch_writeb('M'); - for(j = 0; j < 8; j++) { - slip_arch_writeb(hexchar[addr.u8[j] >> 4]); - slip_arch_writeb(hexchar[addr.u8[j] & 15]); - } - slip_arch_writeb(SLIP_END); - return 0; - } - } -#endif /* SLIP_CONF_ANSWER_MAC_REQUEST */ - /* * Interrupt can not change begin but may change pkt_end. * If pkt_end != begin it will not change again. @@ -221,7 +142,7 @@ slip_poll_handler(uint8_t *outbuf, uint16_t blen) len = 0; break; } - if (esc) { + if(esc) { if(rxbuf[i] == SLIP_ESC_ESC) { outbuf[len] = SLIP_ESC; len++; @@ -245,7 +166,7 @@ slip_poll_handler(uint8_t *outbuf, uint16_t blen) len = 0; break; } - if (esc) { + if(esc) { if(rxbuf[i] == SLIP_ESC_ESC) { outbuf[len] = SLIP_ESC; len++; @@ -266,7 +187,7 @@ slip_poll_handler(uint8_t *outbuf, uint16_t blen) len = 0; break; } - if (esc) { + if(esc) { if(rxbuf[i] == SLIP_ESC_ESC) { outbuf[len] = SLIP_ESC; len++; @@ -332,17 +253,13 @@ PROCESS_THREAD(slip_process, ev, data) /* Move packet from rxbuf to buffer provided by uIP. */ uip_len = slip_poll_handler(&uip_buf[UIP_LLH_LEN], - UIP_BUFSIZE - UIP_LLH_LEN); + UIP_BUFSIZE - UIP_LLH_LEN); if(uip_len > 0) { if(input_callback) { input_callback(); } -#ifdef SLIP_CONF_TCPIP_INPUT - SLIP_CONF_TCPIP_INPUT(); -#else tcpip_input(); -#endif } } @@ -364,7 +281,7 @@ slip_input_byte(unsigned char c) if(c != SLIP_ESC_END && c != SLIP_ESC_ESC) { state = STATE_RUBBISH; SLIP_STATISTICS(slip_rubbish++); - next_free = pkt_end; /* remove rubbish */ + next_free = pkt_end; /* remove rubbish */ return 0; } state = STATE_OK; @@ -389,22 +306,14 @@ slip_input_byte(unsigned char c) } rxbuf[cur_end] = c; -#ifdef SLIP_CONF_MICROSOFT_CHAT - /* There could be a separate poll routine for this. */ - if(c == 'T' && rxbuf[begin] == 'C') { - process_poll(&slip_process); - return 1; - } -#endif /* SLIP_CONF_MICROSOFT_CHAT */ - if(c == SLIP_END) { /* * We have a new packet, possibly of zero length. * * There may already be one packet buffered. */ - if(cur_end != pkt_end) { /* Non zero length. */ - if(begin == pkt_end) { /* None buffered. */ + if(cur_end != pkt_end) { /* Non zero length. */ + if(begin == pkt_end) { /* None buffered. */ pkt_end = cur_end; } else { SLIP_STATISTICS(slip_twopackets++); diff --git a/os/dev/slip.h b/os/dev/slip.h index 759de1a46287dfd73184364408e92cebc19d31ed..bb0ca3bafaa3b39aa5476be9fefbb6632a24cad7 100644 --- a/os/dev/slip.h +++ b/os/dev/slip.h @@ -41,7 +41,7 @@ PROCESS_NAME(slip_process); /** * Send an IP packet from the uIP buffer with SLIP. */ -uint8_t slip_send(void); +void slip_send(void); /** * Input a SLIP byte. @@ -62,13 +62,10 @@ uint8_t slip_send(void); */ int slip_input_byte(unsigned char c); -uint8_t slip_write(const void *ptr, int len); - -/* Did we receive any bytes lately? */ -extern uint8_t slip_active; - -/* Statistics. */ -extern uint16_t slip_rubbish, slip_twopackets, slip_overflow, slip_ip_drop; +/** + * Send using SLIP len bytes starting from the location pointed to by ptr + */ +void slip_write(const void *ptr, int len); /** * Set a function to be called when there is activity on the SLIP diff --git a/examples/rpl-border-router/embedded/project-conf.h b/os/dev/spi-legacy.h similarity index 52% rename from examples/rpl-border-router/embedded/project-conf.h rename to os/dev/spi-legacy.h index b67d39e5643e98669cdb006badabec37dd29569a..d1600c7857b6b03960190f04a023d54189922cc5 100644 --- a/examples/rpl-border-router/embedded/project-conf.h +++ b/os/dev/spi-legacy.h @@ -28,26 +28,65 @@ * */ -#ifndef PROJECT_ROUTER_CONF_H_ -#define PROJECT_ROUTER_CONF_H_ -/*---------------------------------------------------------------------------*/ -/* Include target-specific header */ -#ifdef TARGET_CONF_PATH -#include TARGET_CONF_PATH -#endif /* TARGET_CONF_PATH */ -/*---------------------------------------------------------------------------*/ -#ifndef UIP_FALLBACK_INTERFACE -#define UIP_FALLBACK_INTERFACE rpl_interface -#endif +/** + * \file + * Basic SPI macros + * \author + * Joakim Eriksson <joakime@sics.se> + * Niclas Finne <nfi@sics.se> + */ -#ifndef WEBSERVER_CONF_CFS_CONNS -#define WEBSERVER_CONF_CFS_CONNS 2 -#endif +#ifndef SPI_LEGACY_H_ +#define SPI_LEGACY_H_ + +/* Define macros to use for checking SPI transmission status depending + on if it is possible to wait for TX buffer ready. This is possible + on for example MSP430 but not on AVR. */ +#ifdef SPI_WAITFORTxREADY +#define SPI_WAITFORTx_BEFORE() SPI_WAITFORTxREADY() +#define SPI_WAITFORTx_AFTER() +#define SPI_WAITFORTx_ENDED() SPI_WAITFOREOTx() +#else /* SPI_WAITFORTxREADY */ +#define SPI_WAITFORTx_BEFORE() +#define SPI_WAITFORTx_AFTER() SPI_WAITFOREOTx() +#define SPI_WAITFORTx_ENDED() +#endif /* SPI_WAITFORTxREADY */ + +extern unsigned char spi_busy; + +void spi_init(void); + +/* Write one character to SPI */ +#define SPI_WRITE(data) \ + do { \ + SPI_WAITFORTx_BEFORE(); \ + SPI_TXBUF = data; \ + SPI_WAITFOREOTx(); \ + } while(0) + +/* Write one character to SPI - will not wait for end + useful for multiple writes with wait after final */ +#define SPI_WRITE_FAST(data) \ + do { \ + SPI_WAITFORTx_BEFORE(); \ + SPI_TXBUF = data; \ + SPI_WAITFORTx_AFTER(); \ + } while(0) -#define BORDER_ROUTER_CONF_WEBSERVER 1 +/* Read one character from SPI */ +#define SPI_READ(data) \ + do { \ + SPI_TXBUF = 0; \ + SPI_WAITFOREORx(); \ + data = SPI_RXBUF; \ + } while(0) -#if BORDER_ROUTER_CONF_WEBSERVER -#define UIP_CONF_TCP 1 +/* Flush the SPI read register */ +#ifndef SPI_FLUSH +#define SPI_FLUSH() \ + do { \ + SPI_RXBUF; \ + } while(0) #endif -#endif /* PROJECT_ROUTER_CONF_H_ */ +#endif /* SPI_LEGACY_H_ */ diff --git a/os/dev/spi.c b/os/dev/spi.c new file mode 100644 index 0000000000000000000000000000000000000000..c41cf206f5faa4aae6b682e1bd6d25fea73c440e --- /dev/null +++ b/os/dev/spi.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2016-2017, Yanzi Networks. + * Copyright (c) 2017, University of Bristol - http://www.bristol.ac.uk/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup spi-hal + * @{ + * + * \file + * Implementation of the platform-independent aspects of the SPI HAL + */ +/*---------------------------------------------------------------------------*/ +#include <dev/spi.h> +#include "contiki.h" +#include <stdint.h> +#include <stdbool.h> +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_acquire(spi_device_t *dev) +{ + if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) { + return SPI_DEV_STATUS_EINVAL; + } + + /* lock and open the bus */ + return spi_arch_lock_and_open(dev); +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_release(spi_device_t *dev) +{ + if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) { + return SPI_DEV_STATUS_EINVAL; + } + + /* close and unlock the bus */ + return spi_arch_close_and_unlock(dev); +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_select(spi_device_t *dev) +{ + return spi_arch_select(dev); +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_deselect(spi_device_t *dev) +{ + return spi_arch_deselect(dev); +} +/*---------------------------------------------------------------------------*/ +bool +spi_has_bus(spi_device_t *dev) +{ + if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) { + return false; + } + + return spi_arch_has_lock(dev); +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_write_byte(spi_device_t *dev, uint8_t data) +{ + if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) { + return SPI_DEV_STATUS_EINVAL; + } + + if(!spi_arch_has_lock(dev)) { + return SPI_DEV_STATUS_BUS_LOCKED; + } + + return spi_arch_transfer(dev, &data, 1, 0, 0, 0); +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_write(spi_device_t *dev, const uint8_t *data, int size) +{ + if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) { + return SPI_DEV_STATUS_EINVAL; + } + + if(!spi_arch_has_lock(dev)) { + return SPI_DEV_STATUS_BUS_LOCKED; + } + + return spi_arch_transfer(dev, data, size, 0, 0, 0); +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_read_byte(spi_device_t *dev, uint8_t *buf) +{ + if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) { + return SPI_DEV_STATUS_EINVAL; + } + + if(!spi_arch_has_lock(dev)) { + return SPI_DEV_STATUS_BUS_LOCKED; + } + + return spi_arch_transfer(dev, NULL, 0, buf, 1, 0); +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_read(spi_device_t *dev, uint8_t *buf, int size) +{ + if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) { + return SPI_DEV_STATUS_EINVAL; + } + + if(!spi_arch_has_lock(dev)) { + return SPI_DEV_STATUS_BUS_LOCKED; + } + + return spi_arch_transfer(dev, NULL, 0, buf, size, 0); +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_read_skip(spi_device_t *dev, int size) +{ + if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) { + return SPI_DEV_STATUS_EINVAL; + } + + if(!spi_arch_has_lock(dev)) { + return SPI_DEV_STATUS_BUS_LOCKED; + } + + return spi_arch_transfer(dev, NULL, 0, NULL, 0, size); +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_transfer(spi_device_t *dev, + const uint8_t *wdata, int wsize, + uint8_t *rbuf, int rsize, int ignore) +{ + if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) { + return SPI_DEV_STATUS_EINVAL; + } + + if(!spi_arch_has_lock(dev)) { + return SPI_DEV_STATUS_BUS_LOCKED; + } + + if(wdata == NULL && wsize > 0) { + return SPI_DEV_STATUS_EINVAL; + } + + if(rbuf == NULL && rsize > 0) { + return SPI_DEV_STATUS_EINVAL; + } + + return spi_arch_transfer(dev, wdata, wsize, rbuf, rsize, ignore); +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_read_register(spi_device_t *dev, uint8_t reg, uint8_t *data, int size) +{ + spi_status_t status; + if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) { + return SPI_DEV_STATUS_EINVAL; + } + + /* write the register first (will read a status) */ + status = spi_write_byte(dev, reg); + if(status != SPI_DEV_STATUS_OK) { + return status; + } + + /* then read the value (will read the value) */ + status = spi_read(dev, data, size); + if(status != SPI_DEV_STATUS_OK) { + return status; + } + + return status; +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_strobe(spi_device_t *dev, uint8_t strobe, uint8_t *result) +{ + if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) { + return SPI_DEV_STATUS_EINVAL; + } + + if(!spi_arch_has_lock(dev)) { + return SPI_DEV_STATUS_BUS_LOCKED; + } + + return spi_arch_transfer(dev, &strobe, 1, result, 1, 0); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/os/dev/spi.h b/os/dev/spi.h index 5960c411b064b6082585f228f268ced9a131f2f2..0c9aadc73729389e8118c8ecf9bfb3429c19f292 100644 --- a/os/dev/spi.h +++ b/os/dev/spi.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2010, Swedish Institute of Computer Science. + * Copyright (c) 2016-2017, Yanzi Networks. + * Copyright (c) 2017, University of Bristol - http://www.bristol.ac.uk/ * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,83 +11,339 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. */ - +/*---------------------------------------------------------------------------*/ /** + * \addtogroup dev + * @{ + * + * \defgroup spi-hal SPI Hardware Abstraction Layer + * + * The SPI HAL provides a set of common functions that can be used in a + * platform-independent fashion. + * + * + * @{ + * * \file - * Basic SPI macros - * \author - * Joakim Eriksson <joakime@sics.se> - * Niclas Finne <nfi@sics.se> + * Header file for the SPI HAL */ - +/*---------------------------------------------------------------------------*/ #ifndef SPI_H_ #define SPI_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "gpio-hal.h" -/* Define macros to use for checking SPI transmission status depending - on if it is possible to wait for TX buffer ready. This is possible - on for example MSP430 but not on AVR. */ -#ifdef SPI_WAITFORTxREADY -#define SPI_WAITFORTx_BEFORE() SPI_WAITFORTxREADY() -#define SPI_WAITFORTx_AFTER() -#define SPI_WAITFORTx_ENDED() SPI_WAITFOREOTx() -#else /* SPI_WAITFORTxREADY */ -#define SPI_WAITFORTx_BEFORE() -#define SPI_WAITFORTx_AFTER() SPI_WAITFOREOTx() -#define SPI_WAITFORTx_ENDED() -#endif /* SPI_WAITFORTxREADY */ - -extern unsigned char spi_busy; - -void spi_init(void); - -/* Write one character to SPI */ -#define SPI_WRITE(data) \ - do { \ - SPI_WAITFORTx_BEFORE(); \ - SPI_TXBUF = data; \ - SPI_WAITFOREOTx(); \ - } while(0) - -/* Write one character to SPI - will not wait for end - useful for multiple writes with wait after final */ -#define SPI_WRITE_FAST(data) \ - do { \ - SPI_WAITFORTx_BEFORE(); \ - SPI_TXBUF = data; \ - SPI_WAITFORTx_AFTER(); \ - } while(0) - -/* Read one character from SPI */ -#define SPI_READ(data) \ - do { \ - SPI_TXBUF = 0; \ - SPI_WAITFOREORx(); \ - data = SPI_RXBUF; \ - } while(0) - -/* Flush the SPI read register */ -#ifndef SPI_FLUSH -#define SPI_FLUSH() \ - do { \ - SPI_RXBUF; \ - } while(0) +#include <stdint.h> +#include <stdbool.h> +/*---------------------------------------------------------------------------*/ +/* Include Arch-Specific conf */ +#ifdef SPI_HAL_CONF_ARCH_HDR_PATH +#include SPI_HAL_CONF_ARCH_HDR_PATH +#endif /* SPI_HAL_CONF_ARCH_HDR_PATH */ +/*---------------------------------------------------------------------------*/ +#ifdef SPI_CONF_CONTROLLER_COUNT +/** + * \brief Number of SPI module instances on a chip + */ +#define SPI_CONTROLLER_COUNT SPI_CONF_CONTROLLER_COUNT +#else +#define SPI_CONTROLLER_COUNT 0 #endif +/*---------------------------------------------------------------------------*/ +/* Convenience macros to enumerate SPI module instances on a chip */ +#define SPI_CONTROLLER_SPI0 0 +#define SPI_CONTROLLER_SPI1 1 +/*---------------------------------------------------------------------------*/ +/** + * \brief SPI return codes + * + * @{ + */ +typedef enum { + SPI_DEV_STATUS_OK, /* Everything OK */ + SPI_DEV_STATUS_EINVAL, /* Erroneous input value */ + SPI_DEV_STATUS_BUS_LOCKED, /* SPI bus is already locked */ + SPI_DEV_STATUS_BUS_NOT_OWNED, /* SPI bus is locked by someone else */ + SPI_DEV_STATUS_CLOSED /* SPI bus has not opened properly */ +} spi_status_t; +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief SPI Device Configuration + * + * This is a structure to an architecture-independent SPI configuration. + * + * @{ + */ + +typedef struct spi_device { + gpio_hal_pin_t pin_spi_sck; /* SPI SCK pin */ + gpio_hal_pin_t pin_spi_miso; /* SPI MISO pin */ + gpio_hal_pin_t pin_spi_mosi; /* SPI MOSI pin */ + gpio_hal_pin_t pin_spi_cs; /* SPI Chip Select pin */ + uint32_t spi_bit_rate; /* SPI bit rate */ + uint8_t spi_pha; /* SPI mode phase */ + uint8_t spi_pol; /* SPI mode polarity */ + uint8_t spi_controller; /* ID of SPI controller to use */ +} spi_device_t; +/** @} */ +/*---------------------------------------------------------------------------*/ +/* These are architecture-independent functions to be used by SPI devices. */ +/*---------------------------------------------------------------------------*/ +/** + * \brief Locks and then opens an SPI controller + * \param dev An SPI device configuration which defines the controller + * to be locked and the opening configuration. + * \return SPI return code + */ +spi_status_t spi_acquire(spi_device_t *dev); + +/** + * \brief Closes and then unlocks an SPI controller + * \param dev An SPI device configuration which defines the controller + * to be closed and unlocked. + * \return SPI return code + * + * Releasing an SPI controller should put it in low-power mode. + * This should work only if the device has already locked the SPI + * controller. + */ +spi_status_t spi_release(spi_device_t *dev); + +/** + * \brief Selects the SPI peripheral + * \param dev An SPI device configuration which defines the CS pin. + * \return SPI return code + * + * Clears the CS pin. This should work only if the device has + * already locked the SPI controller. + */ +spi_status_t spi_select(spi_device_t *dev); + +/** + * \brief Deselects the SPI peripheral + * \param dev An SPI device configuration which defines the CS pin. + * \return SPI return code + * + * Sets the CS pin. Lock is not required. + */ +spi_status_t spi_deselect(spi_device_t *dev); + +/** + * \brief Checks if a device has locked an SPI controller + * \param dev An SPI device configuration which defines the controller. + * \return true if the device has the lock, false otherwise. + */ +bool spi_has_bus(spi_device_t *dev); + +/** + * \brief Writes a single byte to an SPI device + * \param dev An SPI device configuration. + * \param data A byte of data + * \return SPI return code + * + * It should work only if the device has already locked the SPI controller. + */ +spi_status_t spi_write_byte(spi_device_t *dev, uint8_t data); + +/** + * \brief Reads a single byte from an SPI device + * \param dev An SPI device configuration. + * \param data A pointer to a byte of data + * \return SPI return code + * + * It should work only if the device has already locked the SPI controller. + */ +spi_status_t spi_read_byte(spi_device_t *dev, uint8_t *data); + +/** + * \brief Writes a buffer to an SPI device + * \param dev An SPI device configuration. + * \param data A pointer to the data + * \param size Size of the data to write + * \return SPI return code + * + * It should work only if the device has already locked the SPI controller. + */ +spi_status_t spi_write(spi_device_t *dev, + const uint8_t *data, int size); + +/** + * \brief Reads a buffer from an SPI device + * \param dev An SPI device configuration. + * \param data A pointer to the data + * \param size Size of the data to read + * \return SPI return code + * + * It should work only if the device has already locked the SPI controller. + */ +spi_status_t spi_read(spi_device_t *dev, uint8_t *data, int size); + +/** + * \brief Reads and ignores data from an SPI device + * \param dev An SPI device configuration. + * \param size Size of the data to read and ignore + * \return SPI return code + * + * Reads size bytes from the SPI and throws them away. + * It should work only if the device has already locked the SPI controller. + */ +spi_status_t spi_read_skip(spi_device_t *dev, int size); + +/** + * \brief Performs a generic SPI transfer + * \param dev An SPI device configuration. + * \param data A pointer to the data to be written. Set it to NULL to + * skip writing. + * \param wsize Size of data to write. + * \param buf A pointer to buffer to copy the data read. Set to NULL + * to skip reading. + * \param rsize Size of data to read. + * \param ignore Size of data to read and ignore. + * \return SPI return code + * + * It should work only if the device has already locked the SPI controller. + * A total of rlen+ignore_len bytes will be read. The first rlen bytes will + * be copied to buf. The remaining ignore_len bytes won't be copied to the + * buffer. The maximum of wlen and rlen+ignore_len of bytes will be transfered. + */ +spi_status_t spi_transfer(spi_device_t *dev, + const uint8_t *data, int wsize, + uint8_t *buf, int rsize, int ignore); + +/** + * \brief Reads and Writes one byte from/to an SPI device + * \param dev An SPI device configuration. + * \param strobe Byte to write + * \param status Pointer to byte to read + * \return SPI return code + * + * It should work only if the device has already locked the SPI controller. + */ +spi_status_t spi_strobe(spi_device_t *dev, uint8_t strobe, + uint8_t *status); + +/** + * \brief Reads a buffer of bytes from a register of an SPI device + * \param dev An SPI device configuration. + * \param reg Register + * \param data A pointer to the data + * \param size Size of the data to read + * \return SPI return code + * + * It should work only if the device has already locked the SPI controller. + */ +spi_status_t spi_read_register(spi_device_t *dev, uint8_t reg, + uint8_t *data, int size); + +/*---------------------------------------------------------------------------*/ +/* These are architecture-specific functions to be implemented by each CPU. */ +/*---------------------------------------------------------------------------*/ + +/** + * \brief Checks if a device has locked an SPI controller + * \param dev An SPI device configuration which defines the controller + * to be checked if it is locked and the respective device. + * \return 1 if the device has the lock, 0 otherwise. + * + */ +bool spi_arch_has_lock(spi_device_t *dev); + +/** + * \brief Checks if an SPI controller is locked by any device + * \param dev An SPI device configuration which defines the controller + * to be checked. + * \return 1 if the controller is locked, 0 otherwise. + * + */ +bool spi_arch_is_bus_locked(spi_device_t *dev); + +/** + * \brief Locks and opens an SPI controller to the configuration specified. + * \param dev An SPI device configuration. + * \return SPI return code + * + * This should work only if the device has already locked the SPI + * controller. + * + */ +spi_status_t spi_arch_lock_and_open(spi_device_t *dev); + +/** + * \brief Closes and unlocks an SPI controller + * \param dev An SPI device configuration that specifies the controller. + * \return SPI return code + * + * This should turn off the SPI controller to put it in low power mode + * and unlock it. + * It should work only if the device has already locked the SPI + * controller. + * + */ +spi_status_t spi_arch_close_and_unlock(spi_device_t *dev); + +/** + * \brief Performs an SPI transfer + * \param dev An SPI device configuration that specifies the controller. + * \param data A pointer to the data to be written. Set it to NULL to + * skip writing. + * \param wlen Length of data to write. + * \param buf A pointer to buffer to copy the data read. Set to NULL + * to skip reading. + * \param rlen Length of data to read. + * \param ignore_len Length of data to read and ignore. + * \return SPI return code + * + * It should work only if the device has already locked the SPI controller. + * A total of rlen+ignore_len bytes will be read. The first rlen bytes will + * be copied to buf. The remaining ignore_len bytes won't be copied to the + * buffer. The maximum of wlen and rlen+ignore_len of bytes will be transfered. + */ +spi_status_t spi_arch_transfer(spi_device_t *dev, + const uint8_t *data, int wlen, + uint8_t *buf, int rlen, + int ignore_len); + +/** + * \brief Selects an SPI device + * \param dev An SPI device configuration that specifies the CS pin. + * \return SPI return code + * + * Clears the CS pin. It should work only if the device has already + * locked the SPI controller. + */ +spi_status_t spi_arch_select(spi_device_t *dev); + +/** + * \brief Deselects an SPI device + * \param dev An SPI device configuration that specifies the CS pin. + * \return SPI return code + * + * Set the CS pin. Locking the SPI controller is not needed. + */ +spi_status_t spi_arch_deselect(spi_device_t *dev); #endif /* SPI_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/os/lib/circular-list.c b/os/lib/circular-list.c new file mode 100644 index 0000000000000000000000000000000000000000..2c04d8418f308897cc2b52294f72562175d34094 --- /dev/null +++ b/os/lib/circular-list.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * Copyright (c) 2017, James Pope + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup circular-singly-linked-list + * @{ + * + * \file + * Implementation of circular singly linked lists + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/circular-list.h" + +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +/*---------------------------------------------------------------------------*/ +struct cl { + struct cl *next; +}; +/*---------------------------------------------------------------------------*/ +void +circular_list_init(circular_list_t cl) +{ + *cl = NULL; +} +/*---------------------------------------------------------------------------*/ +void * +circular_list_head(circular_list_t cl) +{ + return *cl; +} +/*---------------------------------------------------------------------------*/ +void * +circular_list_tail(circular_list_t cl) +{ + struct cl *this; + + if(*cl == NULL) { + return NULL; + } + + for(this = *cl; this->next != *cl; this = this->next); + + return this; +} +/*---------------------------------------------------------------------------*/ +void +circular_list_remove(circular_list_t cl, void *element) +{ + struct cl *this, *previous; + + if(*cl == NULL) { + return; + } + + /* + * We start traversing from the second element. + * The head will be visited last. We always update the list's head after + * removal, just in case we have just removed the head. + */ + previous = *cl; + this = previous->next; + + do { + if(this == element) { + previous->next = this->next; + *cl = this->next == this ? NULL : previous; + return; + } + previous = this; + this = this->next; + } while(this != ((struct cl *)*cl)->next); +} +/*---------------------------------------------------------------------------*/ +void +circular_list_add(circular_list_t cl, void *element) +{ + struct cl *head; + + if(element == NULL) { + return; + } + + /* Don't add twice */ + circular_list_remove(cl, element); + + head = *cl; + + if(head == NULL) { + /* If the list was empty, we update the new element to point to itself */ + ((struct cl *)element)->next = element; + } else { + /* If the list exists, we add the new element between the current head and + * the previously second element. */ + ((struct cl *)element)->next = head->next; + head->next = element; + } + + /* In all cases, the new element becomes the list's new head */ + *cl = element; +} +/*---------------------------------------------------------------------------*/ +unsigned long +circular_list_length(circular_list_t cl) +{ + unsigned long len = 1; + struct cl *this; + + if(circular_list_is_empty(cl)) { + return 0; + } + + for(this = *cl; this->next != *cl; this = this->next) { + len++; + } + + return len; +} +/*---------------------------------------------------------------------------*/ +bool +circular_list_is_empty(circular_list_t cl) +{ + return *cl == NULL ? true : false; +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/lib/circular-list.h b/os/lib/circular-list.h new file mode 100644 index 0000000000000000000000000000000000000000..2edcaf808e3cb605169f9efa8e8f15ee9ebdad8c --- /dev/null +++ b/os/lib/circular-list.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * Copyright (c) 2017, James Pope + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** \addtogroup data + * @{ + * + * \defgroup circular-singly-linked-list Circular, singly-linked list + * + * This library provides functions for the creation and manipulation of + * circular, singly-linked lists. + * + * A circular, singly-linked list is declared using the CIRCULAR_LIST macro. + * Elements must be allocated by the calling code and must be of a C struct + * datatype. In this struct, the first field must be a pointer called \e next. + * This field will be used by the library to maintain the list. Application + * code must not modify this field directly. + * + * Functions that modify the list (add / remove) will, in the general case, + * update the list's head and item order. If you call one of these functions + * as part of a list traversal, it is advised to stop / restart traversing + * after the respective function returns. + * @{ + */ +/*---------------------------------------------------------------------------*/ +#ifndef CIRCULAR_LIST_H_ +#define CIRCULAR_LIST_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +/*---------------------------------------------------------------------------*/ +/** + * \brief Define a circular, singly-linked list. + * + * This macro defines a circular, singly-linked list. + * + * The datatype for elements must be a C struct. The struct's first member must + * be a pointer called \e next. This is used internally by the library to + * maintain data structure integrity and must not be modified directly by + * application code. + * + * \param name The name of the circular, singly-linked list. + */ +#define CIRCULAR_LIST(name) \ + static void *name##_circular_list = NULL; \ + static circular_list_t name = (circular_list_t)&name##_circular_list +/*---------------------------------------------------------------------------*/ +/** + * \brief The circular, singly-linked list datatype + */ +typedef void **circular_list_t; +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialise a circular, singly-linked list. + * \param cl The circular, singly-linked list. + */ +void circular_list_init(circular_list_t cl); + +/** + * \brief Return the tail of a circular, singly-linked list. + * \param cl The circular, singly-linked list. + * \return A pointer to the list's head, or NULL if the list is empty + */ +void *circular_list_head(circular_list_t cl); + +/** + * \brief Return the tail of a circular, singly-linked list. + * \param cl The circular, singly-linked list. + * \return A pointer to the list's tail, or NULL if the list is empty + */ +void *circular_list_tail(circular_list_t cl); + +/** + * \brief Add an element to a circular, singly-linked list. + * \param cl The circular, singly-linked list. + * \param element A pointer to the element to be added. + * + * The caller should make no assumptions as to the position in the list of the + * new element. + * + * After this function returns, the list's head is not guaranteed to be the + * same as it was before the addition. + * + * Calling this function will update the list's head and item order. If you + * call this function as part of a list traversal, it is advised to stop + * traversing after this function returns. + */ +void circular_list_add(circular_list_t cl, void *element); + +/** + * \brief Remove an element from a circular, singly-linked list. + * \param cl The circular, singly-linked list. + * \param element A pointer to the element to be removed. + * + * After this function returns, the list's head is not guaranteed to be the + * same as it was before the addition. + * + * Calling this function will update the list's head and item order. If you + * call this function as part of a list traversal, it is advised to stop + * traversing after this function returns. + */ +void circular_list_remove(circular_list_t cl, void *element); + +/** + * \brief Get the length of a circular, singly-linked list. + * \param cl The circular, singly-linked list. + * \return The number of elements in the list + */ +unsigned long circular_list_length(circular_list_t cl); + +/** + * \brief Determine whether a circular, singly-linked list is empty. + * \param cl The circular, singly-linked list. + * \retval true The list is empty + * \retval false The list is not empty + */ +bool circular_list_is_empty(circular_list_t cl); +/*---------------------------------------------------------------------------*/ +#endif /* CIRCULAR_LIST_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/arch/cpu/cc26xx-cc13xx/dbg.h b/os/lib/dbg-io/dbg.h similarity index 83% rename from arch/cpu/cc26xx-cc13xx/dbg.h rename to os/lib/dbg-io/dbg.h index 4460b6eb4f6a186e6698bda919fc72f647810d54..6440b5eca910503f7a916947e2d6ae6ff081a9c5 100644 --- a/arch/cpu/cc26xx-cc13xx/dbg.h +++ b/os/lib/dbg-io/dbg.h @@ -1,10 +1,11 @@ /* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2015, Nordic Semiconductor * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright @@ -29,16 +30,17 @@ */ /*---------------------------------------------------------------------------*/ /** - * \addtogroup cc26xx + * \addtogroup lib * @{ * - * \defgroup cc26xx-char-io CC13xx/CC26xx Character I/O - * - * CC13xx/CC26xx CPU-specific functions for debugging and SLIP I/O + * \addtogroup dbg-io Portable debugging output functons * @{ * * \file - * Header file for the CC13xx/CC26xx Debug I/O module + * Header file for the dbg-io module. + * \author + * Wojciech Bober <wojciech.bober@nordicsemi.no> + * */ #ifndef DBG_H_ #define DBG_H_ @@ -50,12 +52,14 @@ * \param seq A pointer to the stream * \param len The number of bytes to print * \return The number of printed bytes - * - * This function is an arch-specific implementation required by the dbg-io - * API in cpu/arm/common/dbg-io. It prints a stream of bytes over the - * peripheral used by the platform. */ unsigned int dbg_send_bytes(const unsigned char *seq, unsigned int len); +/** + * \brief Print a character to debug output + * \param c Character to print + * \return Printed character + */ +int dbg_putchar(int c); /*---------------------------------------------------------------------------*/ #endif /* DBG_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/os/lib/dbg-io/printf.c b/os/lib/dbg-io/printf.c new file mode 100644 index 0000000000000000000000000000000000000000..9749f1f7d4e5879d4a61d4e9b023971846cca3ae --- /dev/null +++ b/os/lib/dbg-io/printf.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009, Simon Berg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/dbg-io/dbg.h" + +#include <stdio.h> +#include <string.h> +#include <strformat.h> +/*---------------------------------------------------------------------------*/ +static strformat_result +write_str(void *user_data, const char *data, unsigned int len) +{ + if(len > 0) { + dbg_send_bytes((unsigned char *)data, len); + } + return STRFORMAT_OK; +} +/*---------------------------------------------------------------------------*/ +static strformat_context_t ctxt = +{ + write_str, + NULL +}; +/*---------------------------------------------------------------------------*/ +int +printf(const char *fmt, ...) +{ + int res; + va_list ap; + va_start(ap, fmt); + res = format_str_v(&ctxt, fmt, ap); + va_end(ap); + return res; +} +/*---------------------------------------------------------------------------*/ diff --git a/os/lib/dbg-io/putchar.c b/os/lib/dbg-io/putchar.c new file mode 100644 index 0000000000000000000000000000000000000000..26a35446d25316585e8b427107af4a55943d70a6 --- /dev/null +++ b/os/lib/dbg-io/putchar.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2009, Simon Berg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/dbg-io/dbg.h" + +#include <stdio.h> +#include <string.h> +/*---------------------------------------------------------------------------*/ +int +putchar(int c) +{ + dbg_putchar(c); + return c; +} +/*---------------------------------------------------------------------------*/ diff --git a/os/lib/dbg-io/puts.c b/os/lib/dbg-io/puts.c new file mode 100644 index 0000000000000000000000000000000000000000..93d73d3a571b5337297a580f6a4eac71aa912daf --- /dev/null +++ b/os/lib/dbg-io/puts.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2009, Simon Berg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/dbg-io/dbg.h" + +#include <stdio.h> +#include <string.h> +/*---------------------------------------------------------------------------*/ +int +puts(const char *str) +{ + dbg_send_bytes((unsigned char *)str, strlen(str)); + dbg_putchar('\n'); + return 0; +} +/*---------------------------------------------------------------------------*/ diff --git a/os/lib/dbg-io/snprintf.c b/os/lib/dbg-io/snprintf.c new file mode 100644 index 0000000000000000000000000000000000000000..96f99e568abb2b20ef6b38e0c42f01e5254da826 --- /dev/null +++ b/os/lib/dbg-io/snprintf.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2009, Simon Berg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include <stdio.h> +#include <strformat.h> +#include <string.h> +/*---------------------------------------------------------------------------*/ +struct fmt_buffer { + char *pos; + size_t left; +}; +/*---------------------------------------------------------------------------*/ +static strformat_result +buffer_str(void *user_data, const char *data, unsigned int len) +{ + struct fmt_buffer *buffer = (struct fmt_buffer *)user_data; + if(len >= buffer->left) { + len = buffer->left; + len--; + } + + memcpy(buffer->pos, data, len); + buffer->pos += len; + buffer->left -= len; + return STRFORMAT_OK; +} +/*---------------------------------------------------------------------------*/ +int +snprintf(char *str, size_t size, const char *format, ...) +{ + int res; + va_list ap; + va_start(ap, format); + res = vsnprintf(str, size, format, ap); + va_end(ap); + return res; +} +/*---------------------------------------------------------------------------*/ +int +vsnprintf(char *str, size_t size, const char *format, va_list ap) +{ + struct fmt_buffer buffer; + strformat_context_t ctxt; + int res; + ctxt.write_str = buffer_str; + ctxt.user_data = &buffer; + buffer.pos = str; + buffer.left = size; + res = format_str_v(&ctxt, format, ap); + *buffer.pos = '\0'; + return res; +} +/*---------------------------------------------------------------------------*/ diff --git a/os/lib/dbg-io/sprintf.c b/os/lib/dbg-io/sprintf.c new file mode 100644 index 0000000000000000000000000000000000000000..4ecf5b540a758f99da486dc8ae83ccde0219d3b2 --- /dev/null +++ b/os/lib/dbg-io/sprintf.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2009, Simon Berg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include <stdio.h> +#include <strformat.h> +#include <string.h> +/*---------------------------------------------------------------------------*/ +static strformat_result +buffer_str(void *user_data, const char *data, unsigned int len) +{ + memcpy(*(char **)user_data, data, len); + (*(char **)user_data) += len; + return STRFORMAT_OK; +} +/*---------------------------------------------------------------------------*/ +int +sprintf(char *str, const char *format, ...) +{ + strformat_context_t ctxt; + int res; + va_list ap; + va_start(ap, format); + ctxt.write_str = buffer_str; + ctxt.user_data = &str; + res = format_str_v(&ctxt, format, ap); + *str = '\0'; + va_end(ap); + return res; +} +/*---------------------------------------------------------------------------*/ diff --git a/os/lib/dbg-io/strformat.c b/os/lib/dbg-io/strformat.c new file mode 100644 index 0000000000000000000000000000000000000000..b5ad18f897768356e2f124cc245c2bbb64c8b607 --- /dev/null +++ b/os/lib/dbg-io/strformat.c @@ -0,0 +1,707 @@ +/* + * Copyright (c) 2009, Simon Berg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include <strformat.h> +/*---------------------------------------------------------------------------*/ +#define HAVE_DOUBLE +#define HAVE_LONGLONG + +#ifndef LARGEST_SIGNED +#ifdef HAVE_LONGLONG +#define LARGEST_SIGNED long long int +#else +#define LARGEST_UNSIGNED long int +#endif /* HAVE_LONGLONG */ +#endif /* LARGEST_SIGNED */ + +#ifndef LARGEST_UNSIGNED +#ifdef HAVE_LONGLONG +#define LARGEST_UNSIGNED unsigned long long int +#else +#define LARGEST_UNSIGNED unsigned long int +#endif /* HAVE_LONGLONG */ +#endif /* LARGEST_UNSIGNED */ + +#ifndef POINTER_INT +#define POINTER_INT unsigned long +#endif +/*---------------------------------------------------------------------------*/ +typedef unsigned int FormatFlags; +/*---------------------------------------------------------------------------*/ +#define MAKE_MASK(shift, size) (((1 << size) - 1) << (shift)) +/*---------------------------------------------------------------------------*/ +#define JUSTIFY_SHIFT 0 +#define JUSTIFY_SIZE 1 +#define JUSTIFY_RIGHT 0x0000 +#define JUSTIFY_LEFT 0x0001 +#define JUSTIFY_MASK MAKE_MASK(JUSTIFY_SHIFT, JUSTIFY_SIZE) +/*---------------------------------------------------------------------------*/ +/* How a positive number is prefixed */ +#define POSITIVE_SHIFT (JUSTIFY_SHIFT + JUSTIFY_SIZE) +#define POSITIVE_NONE (0x0000 << POSITIVE_SHIFT) +#define POSITIVE_SPACE (0x0001 << POSITIVE_SHIFT) +#define POSITIVE_PLUS (0x0003 << POSITIVE_SHIFT) +#define POSITIVE_MASK MAKE_MASK(POSITIVE_SHIFT, POSITIVE_SIZE) + +#define POSITIVE_SIZE 2 +/*---------------------------------------------------------------------------*/ +#define ALTERNATE_FORM_SHIFT (POSITIVE_SHIFT + POSITIVE_SIZE) +#define ALTERNATE_FORM_SIZE 1 +#define ALTERNATE_FORM (0x0001 << ALTERNATE_FORM_SHIFT) +/*---------------------------------------------------------------------------*/ +#define PAD_SHIFT (ALTERNATE_FORM_SHIFT + ALTERNATE_FORM_SIZE) +#define PAD_SIZE 1 +#define PAD_SPACE (0x0000 << PAD_SHIFT) +#define PAD_ZERO (0x0001 << PAD_SHIFT) +/*---------------------------------------------------------------------------*/ +#define SIZE_SHIFT (PAD_SHIFT + PAD_SIZE) +#define SIZE_SIZE 3 +#define SIZE_CHAR (0x0001 << SIZE_SHIFT) +#define SIZE_SHORT (0x0002 << SIZE_SHIFT) +#define SIZE_INT (0x0000 << SIZE_SHIFT) +#define SIZE_LONG (0x0003 << SIZE_SHIFT) +#define SIZE_LONGLONG (0x0004 << SIZE_SHIFT) +#define SIZE_MASK MAKE_MASK(SIZE_SHIFT, SIZE_SIZE) +/*---------------------------------------------------------------------------*/ +#define CONV_SHIFT (SIZE_SHIFT + SIZE_SIZE) +#define CONV_SIZE 3 +#define CONV_INTEGER (0x0001 << CONV_SHIFT) +#define CONV_FLOAT (0x0002 << CONV_SHIFT) +#define CONV_POINTER (0x0003 << CONV_SHIFT) +#define CONV_STRING (0x0004 << CONV_SHIFT) +#define CONV_CHAR (0x0005 << CONV_SHIFT) +#define CONV_PERCENT (0x0006 << CONV_SHIFT) +#define CONV_WRITTEN (0x0007 << CONV_SHIFT) +#define CONV_MASK MAKE_MASK(CONV_SHIFT, CONV_SIZE) +/*---------------------------------------------------------------------------*/ +#define RADIX_SHIFT (CONV_SHIFT + CONV_SIZE) +#define RADIX_SIZE 2 +#define RADIX_DECIMAL (0x0001 << RADIX_SHIFT) +#define RADIX_OCTAL (0x0002 << RADIX_SHIFT) +#define RADIX_HEX (0x0003 << RADIX_SHIFT) +#define RADIX_MASK MAKE_MASK(RADIX_SHIFT, RADIX_SIZE) +/*---------------------------------------------------------------------------*/ +#define SIGNED_SHIFT (RADIX_SHIFT + RADIX_SIZE) +#define SIGNED_SIZE 1 +#define SIGNED_NO (0x0000 << SIGNED_SHIFT) +#define SIGNED_YES (0x0001 << SIGNED_SHIFT) +#define SIGNED_MASK MAKE_MASK(SIGNED_SHIFT, SIGNED_SIZE) +/*---------------------------------------------------------------------------*/ +#define CAPS_SHIFT (SIGNED_SHIFT + SIGNED_SIZE) +#define CAPS_SIZE 1 +#define CAPS_NO (0x0000 << CAPS_SHIFT) +#define CAPS_YES (0x0001 << CAPS_SHIFT) +#define CAPS_MASK MAKE_MASK(CAPS_SHIFT, CAPS_SIZE) +/*---------------------------------------------------------------------------*/ +#define FLOAT_SHIFT (CAPS_SHIFT + CAPS_SIZE) +#define FLOAT_SIZE 2 +#define FLOAT_NORMAL (0x0000 << FLOAT_SHIFT) +#define FLOAT_EXPONENT (0x0001 << FLOAT_SHIFT) +#define FLOAT_DEPENDANT (0x0002 << FLOAT_SHIFT) +#define FLOAT_HEX (0x0003 << FLOAT_SHIFT) +#define FLOAT_MASK MAKE_MASK(FLOAT_SHIFT, FLOAT_SIZE) +/*---------------------------------------------------------------------------*/ +#define CHECKCB(res) { if((res) != STRFORMAT_OK) { va_end(ap); return -1; } } +/*---------------------------------------------------------------------------*/ +#define MAXCHARS_HEX ((sizeof(LARGEST_UNSIGNED) * 8) / 4) + +/* Largest number of characters needed for converting an unsigned integer. */ +#define MAXCHARS ((sizeof(LARGEST_UNSIGNED) * 8 + 2) / 3) +/*---------------------------------------------------------------------------*/ +static FormatFlags +parse_flags(const char **posp) +{ + FormatFlags flags = 0; + const char *pos = *posp; + + while(1) { + switch(*pos) { + case '-': + flags |= JUSTIFY_LEFT; + break; + case '+': + flags |= POSITIVE_PLUS; + break; + case ' ': + flags |= POSITIVE_SPACE; + break; + case '#': + flags |= ALTERNATE_FORM; + break; + case '0': + flags |= PAD_ZERO; + break; + default: + *posp = pos; + return flags; + } + + pos++; + } +} +/*---------------------------------------------------------------------------*/ +static unsigned int +parse_uint(const char **posp) +{ + unsigned v = 0; + const char *pos = *posp; + char ch; + + while((ch = *pos) >= '0' && ch <= '9') { + v = v * 10 + (ch - '0'); + pos++; + } + + *posp = pos; + + return v; +} +/*---------------------------------------------------------------------------*/ +static unsigned int +output_uint_decimal(char **posp, LARGEST_UNSIGNED v) +{ + unsigned int len; + char *pos = *posp; + + while(v > 0) { + *--pos = (v % 10) + '0'; + v /= 10; + } + + len = *posp - pos; + *posp = pos; + + return len; +} +/*---------------------------------------------------------------------------*/ +static unsigned int +output_uint_hex(char **posp, LARGEST_UNSIGNED v, unsigned int flags) +{ + unsigned int len; + const char *hex = (flags & CAPS_YES) ? "0123456789ABCDEF" : "0123456789abcdef"; + char *pos = *posp; + + while(v > 0) { + *--pos = hex[(v % 16)]; + v /= 16; + } + + len = *posp - pos; + *posp = pos; + + return len; +} +/*---------------------------------------------------------------------------*/ +static unsigned int +output_uint_octal(char **posp, LARGEST_UNSIGNED v) +{ + unsigned int len; + char *pos = *posp; + + while(v > 0) { + *--pos = (v % 8) + '0'; + v /= 8; + } + + len = *posp - pos; + *posp = pos; + + return len; +} +/*---------------------------------------------------------------------------*/ +static strformat_result +fill_space(const strformat_context_t *ctxt, unsigned int len) +{ + strformat_result res; + static const char buffer[16] = " "; + + while(len > 16) { + res = ctxt->write_str(ctxt->user_data, buffer, 16); + if(res != STRFORMAT_OK) { + return res; + } + len -= 16; + } + + if(len == 0) { + return STRFORMAT_OK; + } + + return ctxt->write_str(ctxt->user_data, buffer, len); +} +/*---------------------------------------------------------------------------*/ +static strformat_result +fill_zero(const strformat_context_t *ctxt, unsigned int len) +{ + strformat_result res; + static const char buffer[16] = "0000000000000000"; + + while(len > 16) { + res = ctxt->write_str(ctxt->user_data, buffer, 16); + if(res != STRFORMAT_OK) { + return res; + } + len -= 16; + } + + if(len == 0) { + return STRFORMAT_OK; + } + return ctxt->write_str(ctxt->user_data, buffer, len); +} +/*---------------------------------------------------------------------------*/ +int +format_str(const strformat_context_t *ctxt, const char *format, ...) +{ + int ret; + va_list ap; + va_start(ap, format); + ret = format_str_v(ctxt, format, ap); + va_end(ap); + return ret; +} +/*---------------------------------------------------------------------------*/ +int +format_str_v(const strformat_context_t *ctxt, const char *format, va_list ap) +{ + unsigned int written = 0; + const char *pos = format; + + while(*pos != '\0') { + FormatFlags flags; + unsigned int minwidth = 0; + int precision = -1; /* Negative means no precision */ + char ch; + const char *start = pos; + + while((ch = *pos) != '\0' && ch != '%') { + pos++; + } + + if(pos != start) { + CHECKCB(ctxt->write_str(ctxt->user_data, start, pos - start)); + written += pos - start; + } + + if(*pos == '\0') { + va_end(ap); + return written; + } + + pos++; + + if(*pos == '\0') { + va_end(ap); + return written; + } + + flags = parse_flags(&pos); + + /* parse width */ + if(*pos >= '1' && *pos <= '9') { + minwidth = parse_uint(&pos); + } else if(*pos == '*') { + int w = va_arg(ap, int); + + if(w < 0) { + flags |= JUSTIFY_LEFT; + minwidth = w; + } else { + minwidth = w; + } + + pos++; + } + + /* parse precision */ + if(*pos == '.') { + pos++; + + if(*pos >= '0' && *pos <= '9') { + precision = parse_uint(&pos); + } else if(*pos == '*') { + pos++; + precision = va_arg(ap, int); + } + } + + if(*pos == 'l') { + pos++; + + if(*pos == 'l') { + flags |= SIZE_LONGLONG; + pos++; + } else { + flags |= SIZE_LONG; + } + } else if(*pos == 'h') { + pos++; + + if(*pos == 'h') { + flags |= SIZE_CHAR; + pos++; + } else { + flags |= SIZE_SHORT; + } + } + + /* parse conversion specifier */ + switch(*pos) { + case 'd': + case 'i': + flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_YES; + break; + case 'u': + flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_NO; + break; + case 'o': + flags |= CONV_INTEGER | RADIX_OCTAL | SIGNED_NO; + break; + case 'x': + flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO; + break; + case 'X': + flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO | CAPS_YES; + break; +#ifdef HAVE_DOUBLE + case 'f': + flags |= CONV_FLOAT | FLOAT_NORMAL; + break; + case 'F': + flags |= CONV_FLOAT | FLOAT_NORMAL | CAPS_YES; + break; + case 'e': + flags |= CONV_FLOAT | FLOAT_EXPONENT; + break; + case 'E': + flags |= CONV_FLOAT | FLOAT_EXPONENT | CAPS_YES; + break; + case 'g': + flags |= CONV_FLOAT | FLOAT_DEPENDANT; + break; + case 'G': + flags |= CONV_FLOAT | FLOAT_DEPENDANT | CAPS_YES; + break; + case 'a': + flags |= CONV_FLOAT | FLOAT_HEX; + break; + case 'A': + flags |= CONV_FLOAT | FLOAT_HEX | CAPS_YES; + break; +#endif + case 'c': + flags |= CONV_CHAR; + break; + case 's': + flags |= CONV_STRING; + break; + case 'p': + flags |= CONV_POINTER; + break; + case 'n': + flags |= CONV_WRITTEN; + break; + case '%': + flags |= CONV_PERCENT; + break; + case '\0': + va_end(ap); + return written; + } + pos++; + + switch(flags & CONV_MASK) { + case CONV_PERCENT: + CHECKCB(ctxt->write_str(ctxt->user_data, "%", 1)); + written++; + break; + case CONV_INTEGER: + { + /* unsigned integers */ + char *prefix = 0; /* sign, "0x" or "0X" */ + unsigned int prefix_len = 0; + char buffer[MAXCHARS]; + char *conv_pos = buffer + MAXCHARS; + unsigned int conv_len = 0; + unsigned int width = 0; + unsigned int precision_fill; + unsigned int field_fill; + LARGEST_UNSIGNED uvalue = 0; + int negative = 0; + + if(precision < 0) { + precision = 1; + } else { + flags &= ~PAD_ZERO; + } + + if(flags & SIGNED_YES) { + /* signed integers */ + LARGEST_SIGNED value = 0; + switch(flags & SIZE_MASK) { + case SIZE_CHAR: + value = (signed char)va_arg(ap, int); + break; + case SIZE_SHORT: + value = (short)va_arg(ap, int); + break; + case SIZE_INT: + value = va_arg(ap, int); + break; +#ifndef HAVE_LONGLONG + case SIZE_LONGLONG: /* Treat long long the same as long */ +#endif + case SIZE_LONG: + value = va_arg(ap, long); + break; +#ifdef HAVE_LONGLONG + case SIZE_LONGLONG: + value = va_arg(ap, long long); + break; +#endif + } + if(value < 0) { + uvalue = -value; + negative = 1; + } else { + uvalue = value; + } + } else { + + switch(flags & SIZE_MASK) { + case SIZE_CHAR: + uvalue = (unsigned char)va_arg(ap, unsigned int); + break; + case SIZE_SHORT: + uvalue = (unsigned short)va_arg(ap, unsigned int); + break; + case SIZE_INT: + uvalue = va_arg(ap, unsigned int); + break; +#ifndef HAVE_LONGLONG + case SIZE_LONGLONG: /* Treat long long the same as long */ +#endif + case SIZE_LONG: + uvalue = va_arg(ap, unsigned long); + break; +#ifdef HAVE_LONGLONG + case SIZE_LONGLONG: + uvalue = va_arg(ap, unsigned long long); + break; +#endif + } + } + + switch(flags & (RADIX_MASK)) { + case RADIX_DECIMAL: + conv_len = output_uint_decimal(&conv_pos, uvalue); + break; + case RADIX_OCTAL: + conv_len = output_uint_octal(&conv_pos, uvalue); + break; + case RADIX_HEX: + conv_len = output_uint_hex(&conv_pos, uvalue, flags); + break; + } + + width += conv_len; + precision_fill = (precision > conv_len) ? precision - conv_len : 0; + if((flags & (RADIX_MASK | ALTERNATE_FORM)) + == (RADIX_OCTAL | ALTERNATE_FORM)) { + if(precision_fill < 1) { + precision_fill = 1; + } + } + + width += precision_fill; + + if((flags & (RADIX_MASK | ALTERNATE_FORM)) + == (RADIX_HEX | ALTERNATE_FORM) && uvalue != 0) { + prefix_len = 2; + if(flags & CAPS_YES) { + prefix = "0X"; + } else { + prefix = "0x"; + } + } + + if(flags & SIGNED_YES) { + if(negative) { + prefix = "-"; + prefix_len = 1; + } else { + switch(flags & POSITIVE_MASK) { + case POSITIVE_SPACE: + prefix = " "; + prefix_len = 1; + break; + case POSITIVE_PLUS: + prefix = "+"; + prefix_len = 1; + break; + } + } + } + + width += prefix_len; + + field_fill = (minwidth > width) ? minwidth - width : 0; + + if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) { + if(flags & PAD_ZERO) { + precision_fill += field_fill; + field_fill = 0; /* Do not double count padding */ + } else { + CHECKCB(fill_space(ctxt, field_fill)); + } + } + + if(prefix_len > 0) { + CHECKCB(ctxt->write_str(ctxt->user_data, prefix, prefix_len)); + } + written += prefix_len; + + CHECKCB(fill_zero(ctxt, precision_fill)); + written += precision_fill; + + CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos, conv_len)); + written += conv_len; + + if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) { + CHECKCB(fill_space(ctxt, field_fill)); + } + written += field_fill; + } + break; + case CONV_STRING: + { + unsigned int field_fill; + unsigned int len; + char *str = va_arg(ap, char *); + + if(str) { + char *pos = str; + while(*pos != '\0') pos++; + len = pos - str; + } else { + str = "(null)"; + len = 6; + } + + if(precision >= 0 && precision < len) { + len = precision; + } + + field_fill = (minwidth > len) ? minwidth - len : 0; + + if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) { + CHECKCB(fill_space(ctxt, field_fill)); + } + + CHECKCB(ctxt->write_str(ctxt->user_data, str, len)); + written += len; + + if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) { + CHECKCB(fill_space(ctxt, field_fill)); + } + written += field_fill; + } + break; + case CONV_POINTER: + { + LARGEST_UNSIGNED uvalue = + (LARGEST_UNSIGNED)(POINTER_INT)va_arg(ap, void *); + char buffer[MAXCHARS_HEX + 3]; + char *conv_pos = buffer + MAXCHARS_HEX + 3; + unsigned int conv_len; + unsigned int field_fill; + + conv_len = output_uint_hex(&conv_pos, uvalue, flags); + + if(conv_len == 0) { + *--conv_pos = '0'; + conv_len++; + } + + *--conv_pos = 'x'; + *--conv_pos = '0'; + *--conv_pos = '#'; + conv_len += 3; + + field_fill = (minwidth > conv_len) ? minwidth - conv_len : 0; + + if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) { + CHECKCB(fill_space(ctxt, field_fill)); + } + + CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos, conv_len)); + written += conv_len; + + if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) { + CHECKCB(fill_space(ctxt, field_fill)); + } + + written += field_fill; + } + break; + case CONV_CHAR: + { + char ch = va_arg(ap, int); + unsigned int field_fill = (minwidth > 1) ? minwidth - 1 : 0; + + if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) { + CHECKCB(fill_space(ctxt, field_fill)); + written += field_fill; + } + + CHECKCB(ctxt->write_str(ctxt->user_data, &ch, 1)); + written++; + + if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) { + CHECKCB(fill_space(ctxt, field_fill)); + } + written += field_fill; + } + break; + case CONV_WRITTEN: + { + int *p = va_arg(ap, int *); + *p = written; + } + break; + } + } + + return written; +} +/*---------------------------------------------------------------------------*/ diff --git a/arch/platform/srf06-cc26xx/srf06/button-sensor.h b/os/lib/dbg-io/strformat.h similarity index 72% rename from arch/platform/srf06-cc26xx/srf06/button-sensor.h rename to os/lib/dbg-io/strformat.h index 1c810c96debd39b70b010320206b565c334aa9c6..478fb7af7f5db812d1d27bb7b479292d7573b24c 100644 --- a/arch/platform/srf06-cc26xx/srf06/button-sensor.h +++ b/os/lib/dbg-io/strformat.h @@ -1,10 +1,11 @@ /* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2009, Simon Berg * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright @@ -28,33 +29,33 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** - * \addtogroup srf06-common-peripherals - * @{ - * - * \file - * Header file for the SmartRF06EB + CC13xx/CC26xxEM Button Driver - */ +#ifndef STRFORMAT_H_ +#define STRFORMAT_H_ /*---------------------------------------------------------------------------*/ -#ifndef BUTTON_SENSOR_H_ -#define BUTTON_SENSOR_H_ +#include "contiki.h" + +#include <stdarg.h> /*---------------------------------------------------------------------------*/ -#include "lib/sensors.h" +#define STRFORMAT_OK 0 +#define STRFORMAT_FAILED 1 /*---------------------------------------------------------------------------*/ -#define BUTTON_SENSOR "Button" +typedef unsigned int strformat_result; /*---------------------------------------------------------------------------*/ -#define BUTTON_SENSOR_VALUE_STATE 0 -#define BUTTON_SENSOR_VALUE_DURATION 1 +/* The data argument may only be considered valid during the function call */ +typedef strformat_result (*strformat_write)(void *user_data, + const char *data, + unsigned int len); -#define BUTTON_SENSOR_VALUE_RELEASED 0 -#define BUTTON_SENSOR_VALUE_PRESSED 1 +typedef struct strformat_context_s { + strformat_write write_str; + void *user_data; +} strformat_context_t; /*---------------------------------------------------------------------------*/ -extern const struct sensors_sensor button_select_sensor; -extern const struct sensors_sensor button_left_sensor; -extern const struct sensors_sensor button_right_sensor; -extern const struct sensors_sensor button_up_sensor; -extern const struct sensors_sensor button_down_sensor; +int format_str(const strformat_context_t *ctxt, const char *format, ...) + __attribute__ ((__format__ (__printf__, 2,3))); + +int +format_str_v(const strformat_context_t *ctxt, const char *format, va_list ap); /*---------------------------------------------------------------------------*/ -#endif /* BUTTON_SENSOR_H_ */ +#endif /* STRFORMAT_H_ */ /*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/os/lib/dbl-circ-list.c b/os/lib/dbl-circ-list.c new file mode 100644 index 0000000000000000000000000000000000000000..35b33a80123272c40a13acf60e95d124a5565b9e --- /dev/null +++ b/os/lib/dbl-circ-list.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * Copyright (c) 2017, James Pope + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup doubly-linked-circular-list + * @{ + * + * \file + * Implementation of circular, doubly-linked lists + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/dbl-circ-list.h" + +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +/*---------------------------------------------------------------------------*/ +struct dblcl { + struct dblcl *next; + struct dblcl *previous; +}; +/*---------------------------------------------------------------------------*/ +void +dbl_circ_list_init(dbl_circ_list_t dblcl) +{ + *dblcl = NULL; +} +/*---------------------------------------------------------------------------*/ +void * +dbl_circ_list_head(dbl_circ_list_t dblcl) +{ + return *dblcl; +} +/*---------------------------------------------------------------------------*/ +void * +dbl_circ_list_tail(dbl_circ_list_t dblcl) +{ + struct dblcl *this; + + if(*dblcl == NULL) { + return NULL; + } + + for(this = *dblcl; this->next != *dblcl; this = this->next); + + return this; +} +/*---------------------------------------------------------------------------*/ +void +dbl_circ_list_remove(dbl_circ_list_t dblcl, void *element) +{ + struct dblcl *this; + + if(*dblcl == NULL || element == NULL) { + return; + } + + this = *dblcl; + + do { + if(this == element) { + this->previous->next = this->next; + this->next->previous = this->previous; + + /* We need to update the head of the list if we removed the head */ + if(*dblcl == element) { + *dblcl = this->next == this ? NULL : this->next; + } + + this->next = NULL; + this->previous = NULL; + + return; + } + + this = this->next; + } while(this != *dblcl); +} +/*---------------------------------------------------------------------------*/ +void +dbl_circ_list_add_head(dbl_circ_list_t dblcl, void *element) +{ + struct dblcl *head; + + if(element == NULL) { + return; + } + + /* Don't add twice */ + dbl_circ_list_remove(dblcl, element); + + head = dbl_circ_list_head(dblcl); + + if(head == NULL) { + /* If the list was empty */ + ((struct dblcl *)element)->next = element; + ((struct dblcl *)element)->previous = element; + } else { + /* If the list was not empty */ + ((struct dblcl *)element)->next = head; + ((struct dblcl *)element)->previous = head->previous; + head->previous->next = element; + head->previous = element; + } + + *dblcl = element; +} +/*---------------------------------------------------------------------------*/ +void +dbl_circ_list_add_tail(dbl_circ_list_t dblcl, void *element) +{ + struct dblcl *tail; + + if(element == NULL) { + return; + } + + /* Don't add twice */ + dbl_circ_list_remove(dblcl, element); + + tail = dbl_circ_list_tail(dblcl); + + if(tail == NULL) { + /* If the list was empty */ + ((struct dblcl *)element)->next = element; + ((struct dblcl *)element)->previous = element; + *dblcl = element; + } else { + /* If the list was not empty */ + ((struct dblcl *)element)->next = *dblcl; + ((struct dblcl *)element)->previous = tail; + tail->next->previous = element; + tail->next = element; + } +} +/*---------------------------------------------------------------------------*/ +void +dbl_circ_list_add_after(dbl_circ_list_t dblcl, void *existing, void *element) +{ + if(element == NULL || existing == NULL) { + return; + } + + /* Don't add twice */ + dbl_circ_list_remove(dblcl, element); + + ((struct dblcl *)element)->next = ((struct dblcl *)existing)->next; + ((struct dblcl *)element)->previous = existing; + ((struct dblcl *)existing)->next->previous = element; + ((struct dblcl *)existing)->next = element; +} +/*---------------------------------------------------------------------------*/ +void +dbl_circ_list_add_before(dbl_circ_list_t dblcl, void *existing, void *element) +{ + if(element == NULL || existing == NULL) { + return; + } + + /* Don't add twice */ + dbl_circ_list_remove(dblcl, element); + + ((struct dblcl *)element)->next = existing; + ((struct dblcl *)element)->previous = ((struct dblcl *)existing)->previous; + ((struct dblcl *)existing)->previous->next = element; + ((struct dblcl *)existing)->previous = element; + + /* If we added before the list's head, we must update the head */ + if(*dblcl == existing) { + *dblcl = element; + } +} +/*---------------------------------------------------------------------------*/ +unsigned long +dbl_circ_list_length(dbl_circ_list_t dblcl) +{ + unsigned long len = 1; + struct dblcl *this; + + if(*dblcl == NULL) { + return 0; + } + + for(this = *dblcl; this->next != *dblcl; this = this->next) { + len++; + } + + return len; +} +/*---------------------------------------------------------------------------*/ +bool +dbl_circ_list_is_empty(dbl_circ_list_t dblcl) +{ + return *dblcl == NULL ? true : false; +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/lib/dbl-circ-list.h b/os/lib/dbl-circ-list.h new file mode 100644 index 0000000000000000000000000000000000000000..08eba8188078b4ee9b927388d9a53d26be65924d --- /dev/null +++ b/os/lib/dbl-circ-list.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * Copyright (c) 2017, James Pope + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** \addtogroup data + * @{ + * + * \defgroup doubly-linked-circular-list Circular, doubly-linked list + * + * This library provides functions for the creation and manipulation of + * circular, doubly-linked lists. + * + * A circular, doubly-linked list is declared using the DBL_CIRC_LIST macro. + * Elements must be allocated by the calling code and must be of a C struct + * datatype. In this struct, the first field must be a pointer called \e next. + * The second field must be a pointer called \e previous. + * These fields will be used by the library to maintain the list. Application + * code must not modify these fields directly. + * + * Functions that modify the list (add / remove) will, in the general case, + * update the list's head and item order. If you call one of these functions + * as part of a list traversal, it is advised to stop / restart traversing + * after the respective function returns. + * @{ + */ +/*---------------------------------------------------------------------------*/ +#ifndef DBL_CIRC_LIST_H_ +#define DBL_CIRC_LIST_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +/*---------------------------------------------------------------------------*/ +/** + * \brief Define a circular, doubly-linked list. + * + * This macro defines a circular, doubly-linked list. + * + * The datatype for elements must be a C struct. + * The struct's first member must be a pointer called \e next. + * The second field must be a pointer called \e previous. + * These fields will be used by the library to maintain the list. Application + * code must not modify these fields directly. + * + * \param name The name of the circular, doubly-linked list. + */ +#define DBL_CIRC_LIST(name) \ + static void *name##_dbl_circ_list = NULL; \ + static dbl_list_t name = (dbl_circ_list_t)&name##_dbl_circ_list +/*---------------------------------------------------------------------------*/ +/** + * \brief The doubly-linked list datatype + */ +typedef void **dbl_circ_list_t; +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialise a circular, doubly-linked list. + * \param dblcl The circular, doubly-linked list. + */ +void dbl_circ_list_init(dbl_circ_list_t dblcl); + +/** + * \brief Return the tail of a circular, doubly-linked list. + * \param dblcl The circular, doubly-linked list. + * \return A pointer to the list's head, or NULL if the list is empty + */ +void *dbl_circ_list_head(dbl_circ_list_t dblcl); + +/** + * \brief Return the tail of a circular, doubly-linked list. + * \param dblcl The circular, doubly-linked list. + * \return A pointer to the list's tail, or NULL if the list is empty + */ +void *dbl_circ_list_tail(dbl_circ_list_t dblcl); + +/** + * \brief Add an element to the head of a circular, doubly-linked list. + * \param dblcl The circular, doubly-linked list. + * \param element A pointer to the element to be added. + * + * Calling this function will update the list's head and item order. If you + * call this function as part of a list traversal, it is advised to stop + * traversing after this function returns. + */ +void dbl_circ_list_add_head(dbl_circ_list_t dblcl, void *element); + +/** + * \brief Add an element to the tail of a circular, doubly-linked list. + * \param dblcl The circular, doubly-linked list. + * \param element A pointer to the element to be added. + * + * Calling this function will update the list's head and item order. If you + * call this function as part of a list traversal, it is advised to stop + * traversing after this function returns. + */ +void dbl_circ_list_add_tail(dbl_circ_list_t dblcl, void *element); + +/** + * \brief Add an element to a circular, doubly linked list after an existing element. + * \param dblcl The circular, doubly-linked list. + * \param existing A pointer to the existing element. + * \param element A pointer to the element to be added. + * + * This function will add \e element after \e existing + * + * The function will not verify that \e existing is already part of the list. + * + * Calling this function will update the list's head and item order. If you + * call this function as part of a list traversal, it is advised to stop + * traversing after this function returns. + */ +void dbl_circ_list_add_after(dbl_circ_list_t dblcl, void *existing, + void *element); + +/** + * \brief Add an element to a circular, doubly linked list before an existing element. + * \param dblcl The circular, doubly-linked list. + * \param existing A pointer to the existing element. + * \param element A pointer to the element to be added. + * + * This function will add \e element before \e existing + * + * The function will not verify that \e existing is already part of the list. + * + * Calling this function will update the list's head and item order. If you + * call this function as part of a list traversal, it is advised to stop + * traversing after this function returns. + */ +void dbl_circ_list_add_before(dbl_circ_list_t dblcl, void *existing, + void *element); + +/** + * \brief Remove an element from a circular, doubly-linked list. + * \param dblcl The circular, doubly-linked list. + * \param element A pointer to the element to be removed. + * + * Calling this function will update the list's head and item order. If you + * call this function as part of a list traversal, it is advised to stop + * traversing after this function returns. + */ +void dbl_circ_list_remove(dbl_circ_list_t dblcl, void *element); + +/** + * \brief Get the length of a circular, doubly-linked list. + * \param dblcl The circular, doubly-linked list. + * \return The number of elements in the list + */ +unsigned long dbl_circ_list_length(dbl_circ_list_t dblcl); + +/** + * \brief Determine whether a circular, doubly-linked list is empty. + * \param dblcl The circular, doubly-linked list. + * \retval true The list is empty + * \retval false The list is not empty + */ +bool dbl_circ_list_is_empty(dbl_circ_list_t dblcl); +/*---------------------------------------------------------------------------*/ +#endif /* DBL_CIRC_LIST_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/os/lib/dbl-list.c b/os/lib/dbl-list.c new file mode 100644 index 0000000000000000000000000000000000000000..7f2f4b587685aee38ea10ac26e91273ff0471885 --- /dev/null +++ b/os/lib/dbl-list.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * Copyright (c) 2017, James Pope + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup doubly-linked-list + * @{ + * + * \file + * Implementation of doubly-linked lists + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/dbl-list.h" + +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +/*---------------------------------------------------------------------------*/ +struct dll { + struct dll *next; + struct dll *previous; +}; +/*---------------------------------------------------------------------------*/ +void +dbl_list_init(dbl_list_t dll) +{ + *dll = NULL; +} +/*---------------------------------------------------------------------------*/ +void * +dbl_list_head(dbl_list_t dll) +{ + return *dll; +} +/*---------------------------------------------------------------------------*/ +void * +dbl_list_tail(dbl_list_t dll) +{ + struct dll *this; + + if(*dll == NULL) { + return NULL; + } + + for(this = *dll; this->next != NULL; this = this->next); + + return this; +} +/*---------------------------------------------------------------------------*/ +void +dbl_list_remove(dbl_list_t dll, void *element) +{ + struct dll *this, *previous, *next; + + if(*dll == NULL || element == NULL) { + return; + } + + for(this = *dll; this != NULL; this = this->next) { + if(this == element) { + previous = this->previous; + next = this->next; + + if(previous) { + previous->next = this->next; + } + + if(next) { + next->previous = this->previous; + } + + if(*dll == this) { + *dll = next; + } + + return; + } + } +} +/*---------------------------------------------------------------------------*/ +void +dbl_list_add_head(dbl_list_t dll, void *element) +{ + struct dll *head; + + if(element == NULL) { + return; + } + + /* Don't add twice */ + dbl_list_remove(dll, element); + + head = dbl_list_head(dll); + + ((struct dll *)element)->previous = NULL; + ((struct dll *)element)->next = head; + + if(head) { + /* If the list was not empty, update ->previous on the old head */ + head->previous = element; + } + + *dll = element; +} +/*---------------------------------------------------------------------------*/ +void +dbl_list_add_tail(dbl_list_t dll, void *element) +{ + struct dll *tail; + + if(element == NULL) { + return; + } + + /* Don't add twice */ + dbl_list_remove(dll, element); + + tail = dbl_list_tail(dll); + + if(tail == NULL) { + /* The list was empty */ + *dll = element; + } else { + tail->next = element; + } + + ((struct dll *)element)->previous = tail; + ((struct dll *)element)->next = NULL; +} +/*---------------------------------------------------------------------------*/ +void +dbl_list_add_after(dbl_list_t dll, void *existing, void *element) +{ + if(element == NULL || existing == NULL) { + return; + } + + /* Don't add twice */ + dbl_list_remove(dll, element); + + ((struct dll *)element)->next = ((struct dll *)existing)->next; + ((struct dll *)element)->previous = existing; + + if(((struct dll *)existing)->next) { + ((struct dll *)existing)->next->previous = element; + } + ((struct dll *)existing)->next = element; +} +/*---------------------------------------------------------------------------*/ +void +dbl_list_add_before(dbl_list_t dll, void *existing, void *element) +{ + if(element == NULL || existing == NULL) { + return; + } + + /* Don't add twice */ + dbl_list_remove(dll, element); + + ((struct dll *)element)->next = existing; + ((struct dll *)element)->previous = ((struct dll *)existing)->previous; + + if(((struct dll *)existing)->previous) { + ((struct dll *)existing)->previous->next = element; + } + ((struct dll *)existing)->previous = element; + + /* If we added before the list's head, we must update the head */ + if(*dll == existing) { + *dll = element; + } +} +/*---------------------------------------------------------------------------*/ +unsigned long +dbl_list_length(dbl_list_t dll) +{ + unsigned long len = 0; + struct dll *this; + + if(*dll == NULL) { + return 0; + } + + for(this = *dll; this != NULL; this = this->next) { + len++; + } + + return len; +} +/*---------------------------------------------------------------------------*/ +bool +dbl_list_is_empty(dbl_list_t dll) +{ + return *dll == NULL ? true : false; +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/lib/dbl-list.h b/os/lib/dbl-list.h new file mode 100644 index 0000000000000000000000000000000000000000..88caf30ce628b95b4abf423e2afe9783b2498de6 --- /dev/null +++ b/os/lib/dbl-list.h @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * Copyright (c) 2017, James Pope + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** \addtogroup data + * @{ + * + * \defgroup doubly-linked-list Doubly-linked list + * + * This library provides functions for the creation and manipulation of + * doubly-linked lists. + * + * A doubly-linked list is declared using the DBL_LIST macro. + * Elements must be allocated by the calling code and must be of a C struct + * datatype. In this struct, the first field must be a pointer called \e next. + * The second field must be a pointer called \e previous. + * These fields will be used by the library to maintain the list. Application + * code must not modify these fields directly. + * + * Functions that modify the list (add / remove) will, in the general case, + * update the list's head and item order. If you call one of these functions + * as part of a list traversal, it is advised to stop / restart traversing + * after the respective function returns. + * @{ + */ +/*---------------------------------------------------------------------------*/ +#ifndef DBL_LIST_H_ +#define DBL_LIST_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +/*---------------------------------------------------------------------------*/ +/** + * \brief Define a doubly-linked list. + * + * This macro defines a doubly-linked list. + * + * The datatype for elements must be a C struct. + * The struct's first member must be a pointer called \e next. + * The second field must be a pointer called \e previous. + * These fields will be used by the library to maintain the list. Application + * code must not modify these fields directly. + * + * \param name The name of the doubly-linked list. + */ +#define DBL_LIST(name) \ + static void *name##_dbl_list = NULL; \ + static dbl_list_t name = (dbl_list_t)&name##_dbl_list +/*---------------------------------------------------------------------------*/ +/** + * \brief The doubly-linked list datatype + */ +typedef void **dbl_list_t; +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialise a doubly-linked list. + * \param dll The doubly-linked list. + */ +void dbl_list_init(dbl_list_t dll); + +/** + * \brief Return the tail of a doubly-linked list. + * \param dll The doubly-linked list. + * \return A pointer to the list's head, or NULL if the list is empty + */ +void *dbl_list_head(dbl_list_t dll); + +/** + * \brief Return the tail of a doubly-linked list. + * \param dll The doubly-linked list. + * \return A pointer to the list's tail, or NULL if the list is empty + */ +void *dbl_list_tail(dbl_list_t dll); + +/** + * \brief Add an element to the head of a doubly-linked list. + * \param dll The doubly-linked list. + * \param element A pointer to the element to be added. + * + * Calling this function will update the list's head and item order. If you + * call this function as part of a list traversal, it is advised to stop + * traversing after this function returns. + */ +void dbl_list_add_head(dbl_list_t dll, void *element); + +/** + * \brief Add an element to the tail of a doubly-linked list. + * \param dll The doubly-linked list. + * \param element A pointer to the element to be added. + * + * Calling this function will update the list's head and item order. If you + * call this function as part of a list traversal, it is advised to stop + * traversing after this function returns. + */ +void dbl_list_add_tail(dbl_list_t dll, void *element); + +/** + * \brief Add an element to a doubly linked list after an existing element. + * \param dll The doubly-linked list. + * \param existing A pointer to the existing element. + * \param element A pointer to the element to be added. + * + * This function will add \e element after \e existing + * + * The function will not verify that \e existing is already part of the list. + * + * Calling this function will update the list's head and item order. If you + * call this function as part of a list traversal, it is advised to stop + * traversing after this function returns. + */ +void dbl_list_add_after(dbl_list_t dll, void *existing, void *element); + +/** + * \brief Add an element to a doubly linked list before an existing element. + * \param dll The doubly-linked list. + * \param existing A pointer to the existing element. + * \param element A pointer to the element to be added. + * + * This function will add \e element before \e existing + * + * The function will not verify that \e existing is already part of the list. + * + * Calling this function will update the list's head and item order. If you + * call this function as part of a list traversal, it is advised to stop + * traversing after this function returns. + */ +void dbl_list_add_before(dbl_list_t dll, void *existing, void *element); + +/** + * \brief Remove an element from a doubly-linked list. + * \param dll The doubly-linked list. + * \param element A pointer to the element to be removed. + * + * Calling this function will update the list's head and item order. If you + * call this function as part of a list traversal, it is advised to stop + * traversing after this function returns. + */ +void dbl_list_remove(dbl_list_t dll, void *element); + +/** + * \brief Get the length of a doubly-linked list. + * \param dll The doubly-linked list. + * \return The number of elements in the list + */ +unsigned long dbl_list_length(dbl_list_t dll); + +/** + * \brief Determine whether a doubly-linked list is empty. + * \param dll The doubly-linked list. + * \retval true The list is empty + * \retval false The list is not empty + */ +bool dbl_list_is_empty(dbl_list_t dll); +/*---------------------------------------------------------------------------*/ +#endif /* DBL_LIST_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/os/lib/heapmem.c b/os/lib/heapmem.c index 54394ff01c1572fa17ed7a8dc19620dd61f47ada..7a90f1357bd6a8ae56a70bdbd892eb7fd097ae62 100644 --- a/os/lib/heapmem.c +++ b/os/lib/heapmem.c @@ -347,7 +347,7 @@ heapmem_alloc(size_t size) chunk->line = line; #endif - PRINTF("%s ptr %p size %u\n", __func__, GET_PTR(chunk), (unsigned)size); + PRINTF("%s ptr %p size %lu\n", __func__, GET_PTR(chunk), (unsigned long)size); return GET_PTR(chunk); } diff --git a/os/lib/list.c b/os/lib/list.c index 401da617ea0181d20cc5c0673b4128353513cb08..afa9df585f32cca18fdc1665a69f62f503f838e7 100644 --- a/os/lib/list.c +++ b/os/lib/list.c @@ -44,15 +44,14 @@ * \addtogroup list * @{ */ - +#include "contiki.h" #include "lib/list.h" -#define NULL 0 - +#include <string.h> +/*---------------------------------------------------------------------------*/ struct list { struct list *next; }; - /*---------------------------------------------------------------------------*/ /** * Initialize a list. @@ -118,13 +117,13 @@ void * list_tail(list_t list) { struct list *l; - + if(*list == NULL) { return NULL; } - + for(l = *list; l->next != NULL; l = l->next); - + return l; } /*---------------------------------------------------------------------------*/ @@ -148,7 +147,7 @@ list_add(list_t list, void *item) list_remove(list, item); ((struct list *)item)->next = NULL; - + l = list_tail(list); if(l == NULL) { @@ -164,8 +163,6 @@ list_add(list_t list, void *item) void list_push(list_t list, void *item) { - /* struct list *l;*/ - /* Make sure not to add the same element twice */ list_remove(list, item); @@ -186,7 +183,7 @@ void * list_chop(list_t list) { struct list *l, *r; - + if(*list == NULL) { return NULL; } @@ -195,12 +192,12 @@ list_chop(list_t list) *list = NULL; return l; } - + for(l = *list; l->next->next != NULL; l = l->next); r = l->next; l->next = NULL; - + return r; } /*---------------------------------------------------------------------------*/ @@ -240,20 +237,20 @@ void list_remove(list_t list, void *item) { struct list *l, *r; - + if(*list == NULL) { return; } - + r = NULL; for(l = *list; l != NULL; l = l->next) { if(l == item) { if(r == NULL) { - /* First on list */ - *list = l->next; + /* First on list */ + *list = l->next; } else { - /* Not first on list */ - r->next = l->next; + /* Not first on list */ + r->next = l->next; } l->next = NULL; return; @@ -305,7 +302,7 @@ list_insert(list_t list, void *previtem, void *newitem) if(previtem == NULL) { list_push(list, newitem); } else { - + list_remove(list, newitem); ((struct list *)newitem)->next = ((struct list *)previtem)->next; ((struct list *)previtem)->next = newitem; } @@ -324,7 +321,7 @@ list_insert(list_t list, void *previtem, void *newitem) void * list_item_next(void *item) { - return item == NULL? NULL: ((struct list *)item)->next; + return item == NULL ? NULL : ((struct list *)item)->next; } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/lib/queue.h b/os/lib/queue.h new file mode 100644 index 0000000000000000000000000000000000000000..9d65fec9e2a55765c03d85e5a7bae69b2f608b1a --- /dev/null +++ b/os/lib/queue.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * Copyright (c) 2017, James Pope + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup data + * @{ + * + * \defgroup queue Queue library + * + * This library provides functions for the creation and manipulation of + * queues. The library is implemented as a wrapper around the list library. + * + * A queue is declared using the QUEUE macro. Queue elements must be + * allocated by the calling code and must be of a C struct datatype. In this + * struct, the first field must be a pointer called \e next. This field will + * be used by the library to maintain the queue. Application code must not + * modify this field directly. + * @{ + */ +/*---------------------------------------------------------------------------*/ +#ifndef QUEUE_H_ +#define QUEUE_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/list.h" + +#include <stdbool.h> +/*---------------------------------------------------------------------------*/ +/** + * \brief The queue data type + */ +typedef list_t queue_t; +/*---------------------------------------------------------------------------*/ +/** + * \brief Define a queue. + * + * This macro defines a queue. + * + * The datatype for elements must be a C struct. The struct's first member must + * be a pointer called \e next. This is used internally by the library to + * maintain data structure integrity and must not be modified directly by + * application code. + * + * \param name The name of the queue. + */ +#define QUEUE(name) LIST(name) +/*---------------------------------------------------------------------------*/ +struct queue { + struct queue *next; +}; +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialise a queue + * \param queue The queue + */ +static inline void +queue_init(queue_t queue) +{ + list_init(queue); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Adds an element to the tail of the queue + * \param queue The queue + * \param element A pointer to the element to be added + */ +static inline void +queue_enqueue(queue_t queue, void *element) +{ + list_add(queue, element); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Removes the element at the front of the queue + * \param queue The queue + * \return A pointer to the element removed + * + * If this function returns NULL if the queue was empty (queue underflow) + */ +static inline void * +queue_dequeue(queue_t queue) +{ + return list_pop(queue); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the front element of the queue, without removing it + * \param queue The queue + * \return A pointer to the element at the front of the queue + */ +static inline void * +queue_peek(queue_t queue) +{ + return list_head(queue); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Check if a queue is empty + * \param queue The queue + * \retval true The queue is empty + * \retval false The queue has at least one element + */ +static inline bool +queue_is_empty(queue_t queue) +{ + return *queue == NULL ? true : false; +} +/*---------------------------------------------------------------------------*/ +#endif /* QUEUE_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/os/lib/stack.h b/os/lib/stack.h new file mode 100644 index 0000000000000000000000000000000000000000..8d56e46ef148bbb644490a49a2040634758ae6c8 --- /dev/null +++ b/os/lib/stack.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * Copyright (c) 2017, James Pope + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup data + * @{ + * + * \defgroup stack-data-structure Stack library + * + * This library provides functions for the creation and manipulation of + * stacks. The library is implemented as a wrapper around the list library. + * + * A stack is declared using the STACK macro. Stack elements must be + * allocated by the calling code and must be of a C struct datatype. In this + * struct, the first field must be a pointer called \e next. This field will + * be used by the library to maintain the stack. Application code must not + * modify this field directly. + * @{ + */ +/*---------------------------------------------------------------------------*/ +#ifndef STACK_H_ +#define STACK_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/list.h" + +#include <stdbool.h> +/*---------------------------------------------------------------------------*/ +/** + * \brief The stack data type + */ +typedef list_t stack_t; +/*---------------------------------------------------------------------------*/ +/** + * \brief Define a stack. + * + * This macro defines a stack. + * + * The datatype for elements must be a C struct. The struct's first member must + * be a pointer called \e next. This is used internally by the library to + * maintain data structure integrity and must not be modified directly by + * application code. + * + * \param name The name of the stack. + */ +#define STACK(name) LIST(name) +/*---------------------------------------------------------------------------*/ +struct stack { + struct stack *next; +}; +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialise a stack + * \param stack The stack + */ +static inline void +stack_init(stack_t stack) +{ + list_init(stack); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Adds an element to the top of the stack + * \param stack The stack + * \param element A pointer to the element to be added + */ +static inline void +stack_push(stack_t stack, void *element) +{ + list_push(stack, element); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Removes the top element from the stack + * \param stack The stack + * \return A pointer to the element popped + * + * If this function returns NULL if the stack was empty (stack underflow) + */ +static inline void * +stack_pop(stack_t stack) +{ + return list_pop(stack); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the top element of the stack, without popping it + * \param stack The stack + * \return A pointer to the element at the top of the stack + */ +static inline void * +stack_peek(stack_t stack) +{ + return list_head(stack); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Check if a stack is empty + * \param stack The stack + * \retval true The stack is empty + * \retval false The stack has at least one element + */ +static inline bool +stack_is_empty(stack_t stack) +{ + return *stack == NULL ? true : false; +} +/*---------------------------------------------------------------------------*/ +#endif /* STACK_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/os/net/app-layer/coap/Makefile.coap b/os/net/app-layer/coap/Makefile.coap new file mode 100644 index 0000000000000000000000000000000000000000..4afecf78aacc201d29890b5511f69612a4001aba --- /dev/null +++ b/os/net/app-layer/coap/Makefile.coap @@ -0,0 +1,31 @@ +MAKE_WITH_DTLS ?= 0 + +ifeq ($(MAKE_WITH_DTLS),1) + + TINYDTLS_PATH := os/net/security/tinydtls + + ifeq (${wildcard $(CONTIKI)/$(TINYDTLS_PATH)/Makefile},) + ${error Could not find the tinyDTLS submodule. Please run "git submodule update --init" and try again} + endif + + CFLAGS += -DWITH_DTLS=1 + + MODULES += os/net/app-layer/coap/tinydtls-support + MODULES += $(TINYDTLS_PATH) ${addprefix $(TINYDTLS_PATH)/,aes sha2 ecc} + + MAKE_COAP_DTLS_KEYSTORE_NONE := 0 + MAKE_COAP_DTLS_KEYSTORE_SIMPLE := 1 + MAKE_COAP_DTLS_KEYSTORE_LWM2M := 2 + + MAKE_COAP_DTLS_KEYSTORE ?= MAKE_COAP_DTLS_KEYSTORE_LWM2M + + ifeq ($(MAKE_COAP_DTLS_KEYSTORE),MAKE_COAP_DTLS_KEYSTORE_SIMPLE) + CFLAGS += -DCOAP_DTLS_KEYSTORE_CONF_WITH_SIMPLE=1 + else ifeq ($(MAKE_COAP_DTLS_KEYSTORE),MAKE_COAP_DTLS_KEYSTORE_LWM2M) + CFLAGS += -DCOAP_DTLS_KEYSTORE_CONF_WITH_LWM2M=1 + else ifeq ($(MAKE_COAP_DTLS_KEYSTORE),MAKE_COAP_DTLS_KEYSTORE_NONE) + # No C flag needed for no keystore + else + ${error Unsupported CoAP DTLS keystore: $(MAKE_COAP_DTLS_KEYSTORE)} + endif +endif diff --git a/os/net/app-layer/coap/coap-block1.c b/os/net/app-layer/coap/coap-block1.c index 6ecdce7c600ce4da3df86fb116ed17a59536943a..600c09b279e93399be23b5e5bf2acfc667dc2f3f 100644 --- a/os/net/app-layer/coap/coap-block1.c +++ b/os/net/app-layer/coap/coap-block1.c @@ -36,24 +36,23 @@ * Lars Schmertmann <SmallLars@t-online.de> */ -#include <stdio.h> +/** + * \addtogroup coap + * @{ + */ + #include <string.h> +#include <inttypes.h> #include "coap.h" #include "coap-block1.h" -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap" +#define LOG_LEVEL LOG_LEVEL_COAP -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /** * \brief Block 1 support within a coap-ressource @@ -77,39 +76,39 @@ * -1 if initialisation failed */ int -coap_block1_handler(void *request, void *response, uint8_t *target, size_t *len, size_t max_len) +coap_block1_handler(coap_message_t *request, coap_message_t *response, + uint8_t *target, size_t *len, size_t max_len) { const uint8_t *payload = 0; - int pay_len = REST.get_request_payload(request, &payload); + int pay_len = coap_get_payload(request, &payload); if(!pay_len || !payload) { - erbium_status_code = REST.status.BAD_REQUEST; + coap_status_code = BAD_REQUEST_4_00; coap_error_message = "NoPayload"; return -1; } - coap_packet_t *packet = (coap_packet_t *)request; - - if(packet->block1_offset + pay_len > max_len) { - erbium_status_code = REST.status.REQUEST_ENTITY_TOO_LARGE; + if(request->block1_offset + pay_len > max_len) { + coap_status_code = REQUEST_ENTITY_TOO_LARGE_4_13; coap_error_message = "Message to big"; return -1; } if(target && len) { - memcpy(target + packet->block1_offset, payload, pay_len); - *len = packet->block1_offset + pay_len; + memcpy(target + request->block1_offset, payload, pay_len); + *len = request->block1_offset + pay_len; } - if(IS_OPTION(packet, COAP_OPTION_BLOCK1)) { - PRINTF("Blockwise: block 1 request: Num: %u, More: %u, Size: %u, Offset: %u\n", - packet->block1_num, - packet->block1_more, - packet->block1_size, - packet->block1_offset); + if(coap_is_option(request, COAP_OPTION_BLOCK1)) { + LOG_DBG("Blockwise: block 1 request: Num: %"PRIu32 + ", More: %u, Size: %u, Offset: %"PRIu32"\n", + request->block1_num, + request->block1_more, + request->block1_size, + request->block1_offset); - coap_set_header_block1(response, packet->block1_num, packet->block1_more, packet->block1_size); - if(packet->block1_more) { + coap_set_header_block1(response, request->block1_num, request->block1_more, request->block1_size); + if(request->block1_more) { coap_set_status_code(response, CONTINUE_2_31); return 1; } @@ -117,3 +116,5 @@ coap_block1_handler(void *request, void *response, uint8_t *target, size_t *len, return 0; } +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-block1.h b/os/net/app-layer/coap/coap-block1.h index a6b1de5ab17761fd2d896a1d242f4d2d42d1bf01..50638ef6642b091ee207cd7c228972290f15265c 100644 --- a/os/net/app-layer/coap/coap-block1.h +++ b/os/net/app-layer/coap/coap-block1.h @@ -36,12 +36,20 @@ * Lars Schmertmann <SmallLars@t-online.de> */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_BLOCK1_H_ #define COAP_BLOCK1_H_ +#include "coap.h" #include <stddef.h> #include <stdint.h> -int coap_block1_handler(void *request, void *response, uint8_t *target, size_t *len, size_t max_len); +int coap_block1_handler(coap_message_t *request, coap_message_t *response, + uint8_t *target, size_t *len, size_t max_len); #endif /* COAP_BLOCK1_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-blocking-api.c b/os/net/app-layer/coap/coap-blocking-api.c new file mode 100644 index 0000000000000000000000000000000000000000..1be7cbe7cd9f2d760f81df0fe4d5d4bc58e1974a --- /dev/null +++ b/os/net/app-layer/coap/coap-blocking-api.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * CoAP implementation for the REST Engine. + * \author + * Matthias Kovatsch <kovatsch@inf.ethz.ch> + */ + +/** + * \addtogroup coap + * @{ + */ + +#include "coap-engine.h" +#include "coap-blocking-api.h" +#include "sys/cc.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap" +#define LOG_LEVEL LOG_LEVEL_COAP + +/*---------------------------------------------------------------------------*/ +/*- Client Part -------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +void +coap_blocking_request_callback(void *callback_data, coap_message_t *response) +{ + coap_request_state_t *state = (coap_request_state_t *)callback_data; + + state->response = response; + process_poll(state->process); +} +/*---------------------------------------------------------------------------*/ +PT_THREAD(coap_blocking_request + (coap_request_state_t *state, process_event_t ev, + coap_endpoint_t *remote_ep, + coap_message_t *request, + coap_blocking_response_handler_t request_callback)) +{ + PT_BEGIN(&state->pt); + + static uint32_t res_block; + static uint8_t more; + static uint8_t block_error; + + state->block_num = 0; + state->response = NULL; + state->process = PROCESS_CURRENT(); + + more = 0; + res_block = 0; + block_error = 0; + + do { + request->mid = coap_get_mid(); + if((state->transaction = coap_new_transaction(request->mid, remote_ep))) { + state->transaction->callback = coap_blocking_request_callback; + state->transaction->callback_data = state; + + if(state->block_num > 0) { + coap_set_header_block2(request, state->block_num, 0, + COAP_MAX_CHUNK_SIZE); + } + state->transaction->message_len = coap_serialize_message(request, + state-> + transaction-> + message); + + coap_send_transaction(state->transaction); + LOG_DBG("Requested #%"PRIu32" (MID %u)\n", state->block_num, request->mid); + + PT_YIELD_UNTIL(&state->pt, ev == PROCESS_EVENT_POLL); + + if(!state->response) { + LOG_WARN("Server not responding\n"); + PT_EXIT(&state->pt); + } + + coap_get_header_block2(state->response, &res_block, &more, NULL, NULL); + + LOG_DBG("Received #%"PRIu32"%s (%u bytes)\n", res_block, more ? "+" : "", + state->response->payload_len); + + if(res_block == state->block_num) { + request_callback(state->response); + ++(state->block_num); + } else { + LOG_WARN("WRONG BLOCK %"PRIu32"/%"PRIu32"\n", + res_block, state->block_num); + ++block_error; + } + } else { + LOG_WARN("Could not allocate transaction buffer"); + PT_EXIT(&state->pt); + } + } while(more && block_error < COAP_MAX_ATTEMPTS); + + PT_END(&state->pt); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-blocking-api.h b/os/net/app-layer/coap/coap-blocking-api.h new file mode 100644 index 0000000000000000000000000000000000000000..d9a916c043eb90f3094bef82c0d23363d5ba9b65 --- /dev/null +++ b/os/net/app-layer/coap/coap-blocking-api.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \addtogroup coap + * @{ + */ + +#ifndef COAP_BLOCKING_API_H_ +#define COAP_BLOCKING_API_H_ + +#include "sys/pt.h" +#include "coap-transactions.h" + +/*---------------------------------------------------------------------------*/ +/*- Client Part -------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +typedef struct coap_request_state { + struct pt pt; + struct process *process; + coap_transaction_t *transaction; + coap_message_t *response; + uint32_t block_num; +} coap_request_state_t; + +typedef void (* coap_blocking_response_handler_t)(coap_message_t *response); + +PT_THREAD(coap_blocking_request + (coap_request_state_t *state, process_event_t ev, + coap_endpoint_t *remote, + coap_message_t *request, + coap_blocking_response_handler_t request_callback)); + +#define COAP_BLOCKING_REQUEST(server_endpoint, request, chunk_handler) \ + { \ + static coap_request_state_t request_state; \ + PT_SPAWN(process_pt, &request_state.pt, \ + coap_blocking_request(&request_state, ev, \ + server_endpoint, \ + request, chunk_handler) \ + ); \ + } + +#endif /* COAP_BLOCKING_API_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-callback-api.c b/os/net/app-layer/coap/coap-callback-api.c new file mode 100644 index 0000000000000000000000000000000000000000..b1b05597e2d4ff2100de5116d2fa02fd54b43de4 --- /dev/null +++ b/os/net/app-layer/coap/coap-callback-api.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + */ + +/** + * \file + * Callback API for doing CoAP requests + * Adapted from the blocking API + * \author + * Joakim Eriksson, joakime@sics.se + */ + +/** + * \addtogroup coap + * @{ + */ + +#include "coap-engine.h" +#include "coap-callback-api.h" +#include "coap-transactions.h" +#include "sys/cc.h" +#include <stdlib.h> +#include <string.h> + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap" +#define LOG_LEVEL LOG_LEVEL_COAP + +/* These should go into the state struct so that we can have multiple + requests */ + +static uint32_t res_block; +static uint8_t more; +static uint8_t block_error; + +static void coap_request_callback(void *callback_data, coap_message_t *response); + +/*---------------------------------------------------------------------------*/ + +static void +progress_request(coap_request_state_t *state) { + coap_message_t *request = state->request; + request->mid = coap_get_mid(); + if((state->transaction = + coap_new_transaction(request->mid, state->remote_endpoint))) { + state->transaction->callback = coap_request_callback; + state->transaction->callback_data = state; + + if(state->block_num > 0) { + coap_set_header_block2(request, state->block_num, 0, + COAP_MAX_CHUNK_SIZE); + } + state->transaction->message_len = + coap_serialize_message(request, state->transaction->message); + + coap_send_transaction(state->transaction); + LOG_DBG("Requested #%"PRIu32" (MID %u)\n", state->block_num, request->mid); + } +} + +/*---------------------------------------------------------------------------*/ + +static void +coap_request_callback(void *callback_data, coap_message_t *response) +{ + coap_request_state_t *state = (coap_request_state_t *)callback_data; + uint32_t res_block1; + + state->response = response; + + LOG_DBG("request callback\n"); + + if(!state->response) { + LOG_WARN("Server not responding giving up...\n"); + state->callback(state); + return; + } + + /* Got a response */ + coap_get_header_block2(state->response, &res_block, &more, NULL, NULL); + coap_get_header_block1(state->response, &res_block1, NULL, NULL, NULL); + + LOG_DBG("Received #%lu%s B1:%lu (%u bytes)\n", + (unsigned long)res_block, (unsigned)more ? "+" : "", + (unsigned long)res_block1, + state->response->payload_len); + + if(res_block == state->block_num) { + /* Call the callback function as we have more data */ + state->callback(state); + /* this is only for counting BLOCK2 blocks.*/ + ++(state->block_num); + } else { + LOG_WARN("WRONG BLOCK %"PRIu32"/%"PRIu32"\n", res_block, state->block_num); + ++block_error; + } + + if(more && block_error < COAP_MAX_ATTEMPTS) { + progress_request(state); + } else { + /* failure - now we give up and notify the callback */ + state->response = NULL; + state->callback(state); + } +} + +/*---------------------------------------------------------------------------*/ + +void +coap_send_request(coap_request_state_t *state, coap_endpoint_t *endpoint, + coap_message_t *request, + void (*callback)(coap_request_state_t *state)) +{ + /* can we have these variables shared between multiple requests? */ + /* ripped from blocking request */ + more = 0; + res_block = 0; + block_error = 0; + + state->block_num = 0; + state->response = NULL; + state->request = request; + state->remote_endpoint = endpoint; + state->callback = callback; + + progress_request(state); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/arch/platform/native/dev/leds-arch.c b/os/net/app-layer/coap/coap-callback-api.h similarity index 64% rename from arch/platform/native/dev/leds-arch.c rename to os/net/app-layer/coap/coap-callback-api.h index 1308c57dc151245d94ed05bc3b9f14c984e43be6..6de7ab587320144c7f1f987b2ea0958d3fa43c19 100644 --- a/arch/platform/native/dev/leds-arch.c +++ b/os/net/app-layer/coap/coap-callback-api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Swedish Institute of Computer Science. + * Copyright (c) 2016, SICS Swedish ICT * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,35 +26,48 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * This file is part of the Contiki operating system. * */ /** * \file - * A brief description of what this file is. + * Callback API for doing CoAP requests + * Adapted from the blocking API * \author - * Adam Dunkels <adam@sics.se> + * Joakim Eriksson, joakime@sics.se */ -#include "dev/leds.h" -static unsigned char leds; -/*---------------------------------------------------------------------------*/ -void -leds_arch_init(void) -{ - leds = 0; -} -/*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - return leds; -} +/** + * \addtogroup coap + * @{ + */ + +#ifndef COAP_CALLBACK_API_H_ +#define COAP_CALLBACK_API_H_ + +#include "coap-engine.h" +#include "coap-transactions.h" +#include "sys/cc.h" + /*---------------------------------------------------------------------------*/ -void -leds_arch_set(unsigned char l) -{ - leds = l; -} +/*- Client Part -------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +typedef struct coap_request_state coap_request_state_t; + +struct coap_request_state { + coap_transaction_t *transaction; + coap_message_t *response; + coap_message_t *request; + coap_endpoint_t *remote_endpoint; + uint32_t block_num; + void *user_data; + coap_timer_t coap_timer; + void (*callback)(coap_request_state_t *state); +}; + +void coap_send_request(coap_request_state_t *state, coap_endpoint_t *endpoint, + coap_message_t *request, + void (*callback)(coap_request_state_t *state)); + +#endif /* COAP_CALLBACK_API_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-conf.h b/os/net/app-layer/coap/coap-conf.h index 2aabc4be49c6850b1ac85f57ed860a40fd596bc1..911017ed8cba186205cdb7a66f27aeeee41b2b50 100644 --- a/os/net/app-layer/coap/coap-conf.h +++ b/os/net/app-layer/coap/coap-conf.h @@ -36,8 +36,33 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ -#ifndef ER_COAP_CONF_H_ -#define ER_COAP_CONF_H_ +/** + * \addtogroup coap + * @{ + */ + +#ifndef COAP_CONF_H_ +#define COAP_CONF_H_ + +#include "contiki.h" + +/* + * The maximum buffer size that is provided for resource responses and must be + * respected due to the limited IP buffer. Larger data must be handled by the + * resource and will be sent chunk-wise through a TCP stream or CoAP blocks. + */ +#ifndef COAP_MAX_CHUNK_SIZE +#ifdef REST_MAX_CHUNK_SIZE +#define COAP_MAX_CHUNK_SIZE REST_MAX_CHUNK_SIZE +#else /* REST_MAX_CHUNK_SIZE */ +#define COAP_MAX_CHUNK_SIZE 64 +#endif /* REST_MAX_CHUNK_SIZE */ +#endif /* COAP_MAX_CHUNK_SIZE */ + +/* Define REST_MAX_CHUNK_SIZE for backward compatibility */ +#ifndef REST_MAX_CHUNK_SIZE +#define REST_MAX_CHUNK_SIZE COAP_MAX_CHUNK_SIZE +#endif /* REST_MAX_CHUNK_SIZE */ /* Features that can be disabled to achieve smaller memory footprint */ #ifndef COAP_LINK_FORMAT_FILTERING @@ -78,4 +103,5 @@ #define COAP_OBSERVE_REFRESH_INTERVAL 20 #endif /* COAP_OBSERVE_REFRESH_INTERVAL */ -#endif /* ER_COAP_CONF_H_ */ +#endif /* COAP_CONF_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-constants.h b/os/net/app-layer/coap/coap-constants.h index cfa73abcf08222bad2e0c13f7b0fc11fd45d5a65..f73a5b950bafab66ba8d4bcf9fdae823f485bf8d 100644 --- a/os/net/app-layer/coap/coap-constants.h +++ b/os/net/app-layer/coap/coap-constants.h @@ -36,10 +36,16 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ -#ifndef ER_COAP_CONSTANTS_H_ -#define ER_COAP_CONSTANTS_H_ +/** + * \addtogroup coap + * @{ + */ + +#ifndef COAP_CONSTANTS_H_ +#define COAP_CONSTANTS_H_ #define COAP_DEFAULT_PORT 5683 +#define COAP_DEFAULT_SECURE_PORT 5684 #define COAP_DEFAULT_MAX_AGE 60 #define COAP_RESPONSE_TIMEOUT 3 @@ -163,4 +169,24 @@ typedef enum { APPLICATION_X_OBIX_BINARY = 51 } coap_content_format_t; -#endif /* ER_COAP_CONSTANTS_H_ */ +/** + * Resource flags for allowed methods and special functionalities. + */ +typedef enum { + NO_FLAGS = 0, + + /* methods to handle */ + METHOD_GET = (1 << 0), + METHOD_POST = (1 << 1), + METHOD_PUT = (1 << 2), + METHOD_DELETE = (1 << 3), + + /* special flags */ + HAS_SUB_RESOURCES = (1 << 4), + IS_SEPARATE = (1 << 5), + IS_OBSERVABLE = (1 << 6), + IS_PERIODIC = (1 << 7) +} coap_resource_flags_t; + +#endif /* COAP_CONSTANTS_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-endpoint.h b/os/net/app-layer/coap/coap-endpoint.h new file mode 100644 index 0000000000000000000000000000000000000000..96979124158cd160d03dc6b6186f5cda7dafb794 --- /dev/null +++ b/os/net/app-layer/coap/coap-endpoint.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2016-2018, SICS, Swedish ICT AB. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * \file + * API to address CoAP endpoints + * \author + * Niclas Finne <nfi@sics.se> + * Joakim Eriksson <joakime@sics.se> + */ + +/** + * \addtogroup coap-transport + * @{ + */ + +#ifndef COAP_ENDPOINT_H_ +#define COAP_ENDPOINT_H_ + +#include "contiki.h" +#include <stdlib.h> + +#ifndef COAP_ENDPOINT_CUSTOM +#include "net/ipv6/uip.h" + +typedef struct { + uip_ipaddr_t ipaddr; + uint16_t port; + uint8_t secure; +} coap_endpoint_t; +#endif /* COAP_ENDPOINT_CUSTOM */ + +/** + * \brief Copy a CoAP endpoint from one memory area to another. + * + * \param dest A pointer to a CoAP endpoint to copy to. + * \param src A pointer to a CoAP endpoint to copy from. + */ +void coap_endpoint_copy(coap_endpoint_t *dest, const coap_endpoint_t *src); + +/** + * \brief Compare two CoAP endpoints. + * + * \param e1 A pointer to the first CoAP endpoint. + * \param e2 A pointer to the second CoAP endpoint. + * \return Non-zero if the endpoints are identical and zero otherwise. + */ +int coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2); + +/** + * \brief Print a CoAP endpoint via the logging module. + * + * \param ep A pointer to the CoAP endpoint to log. + */ +void coap_endpoint_log(const coap_endpoint_t *ep); + +/** + * \brief Print a CoAP endpoint. + * + * \param ep A pointer to the CoAP endpoint to print. + */ +void coap_endpoint_print(const coap_endpoint_t *ep); + +/** + * \brief Print a CoAP endpoint to a string. The output is always + * null-terminated unless size is zero. + * + * \param str The string to write to. + * \param size The max number of characters to write. + * \param ep A pointer to the CoAP endpoint to print. + * \return Returns the number of characters needed for the output + * excluding the ending null-terminator or negative if an + * error occurred. + */ +int coap_endpoint_snprint(char *str, size_t size, + const coap_endpoint_t *ep); + +/** + * \brief Parse a CoAP endpoint. + * + * \param text The string to parse. + * \param size The max number of characters in the string. + * \param ep A pointer to the CoAP endpoint to write to. + * \return Returns non-zero if the endpoint was successfully parsed and + * zero otherwise. + */ +int coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep); + +/** + * \brief Check if a CoAP endpoint is secure (encrypted). + * + * \param ep A pointer to a CoAP endpoint. + * \return Returns non-zero if the endpoint is secure and zero otherwise. + */ +int coap_endpoint_is_secure(const coap_endpoint_t *ep); + +/** + * \brief Check if a CoAP endpoint is connected. + * + * \param ep A pointer to a CoAP endpoint. + * \return Returns non-zero if the endpoint is connected and zero otherwise. + */ +int coap_endpoint_is_connected(const coap_endpoint_t *ep); + +/** + * \brief Request a connection to a CoAP endpoint. + * + * \param ep A pointer to a CoAP endpoint. + * \return Returns zero if an error occured and non-zero otherwise. + */ +int coap_endpoint_connect(coap_endpoint_t *ep); + +/** + * \brief Request that any connection to a CoAP endpoint is discontinued. + * + * \param ep A pointer to a CoAP endpoint. + */ +void coap_endpoint_disconnect(coap_endpoint_t *ep); + +#endif /* COAP_ENDPOINT_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-engine.c b/os/net/app-layer/coap/coap-engine.c index 8cde3b836388fc8d3a7415e7ebc5579bc146424a..cbfa70ee93eaa84423c7b8d0b108ebab3b3d6a26 100644 --- a/os/net/app-layer/coap/coap-engine.c +++ b/os/net/app-layer/coap/coap-engine.c @@ -31,490 +31,489 @@ /** * \file - * CoAP implementation for the REST Engine. + * CoAP implementation Engine. * \author * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +/** + * \addtogroup coap + * @{ + */ + +#include "coap-engine.h" #include "sys/cc.h" +#include "lib/list.h" #include <stdio.h> #include <stdlib.h> +#include <inttypes.h> #include <string.h> -#include "coap-engine.h" -#define DEBUG 0 -#if DEBUG -#include <stdio.h> -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-eng" +#define LOG_LEVEL LOG_LEVEL_COAP -PROCESS(coap_engine, "CoAP Engine"); +static void process_callback(coap_timer_t *t); + +/* + * To be called by HTTP/COAP server as a callback function when a new service + * request appears. This function dispatches the corresponding CoAP service. + */ +static int invoke_coap_resource_service(coap_message_t *request, + coap_message_t *response, + uint8_t *buffer, uint16_t buffer_size, + int32_t *offset); /*---------------------------------------------------------------------------*/ /*- Variables ---------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -static service_callback_t service_cbk = NULL; +LIST(coap_handlers); +LIST(coap_resource_services); +static uint8_t is_initialized = 0; /*---------------------------------------------------------------------------*/ -/*- Internal API ------------------------------------------------------------*/ +/*- CoAP service handlers---------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -static int -coap_receive(void) +void +coap_add_handler(coap_handler_t *handler) +{ + list_add(coap_handlers, handler); +} +/*---------------------------------------------------------------------------*/ +void +coap_remove_handler(coap_handler_t *handler) +{ + list_remove(coap_handlers, handler); +} +/*---------------------------------------------------------------------------*/ +coap_handler_status_t +coap_call_handlers(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t buffer_size, int32_t *offset) { - erbium_status_code = NO_ERROR; + coap_handler_status_t status; + coap_handler_t *r; + for(r = list_head(coap_handlers); r != NULL; r = r->next) { + if(r->handler) { + status = r->handler(request, response, buffer, buffer_size, offset); + if(status != COAP_HANDLER_STATUS_CONTINUE) { + /* Request handled. */ + + /* Check response code before doing observe! */ + if(request->code == COAP_GET) { + coap_observe_handler(NULL, request, response); + } + + return status; + } + } + } + return COAP_HANDLER_STATUS_CONTINUE; +} +/*---------------------------------------------------------------------------*/ +static CC_INLINE coap_handler_status_t +call_service(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t buffer_size, int32_t *offset) +{ + coap_handler_status_t status; + status = coap_call_handlers(request, response, buffer, buffer_size, offset); + if(status != COAP_HANDLER_STATUS_CONTINUE) { + return status; + } + status = invoke_coap_resource_service(request, response, buffer, buffer_size, offset); + if(status != COAP_HANDLER_STATUS_CONTINUE) { + return status; + } + + coap_set_status_code(response, NOT_FOUND_4_04); - PRINTF("handle_incoming_data(): received uip_datalen=%u \n", - (uint16_t)uip_datalen()); + return COAP_HANDLER_STATUS_CONTINUE; +} + +/*---------------------------------------------------------------------------*/ +/*- Server Part -------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +/* the discover resource is automatically included for CoAP */ +extern coap_resource_t res_well_known_core; +/*---------------------------------------------------------------------------*/ +/*- Internal API ------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +int +coap_receive(const coap_endpoint_t *src, + uint8_t *payload, uint16_t payload_length) +{ /* static declaration reduces stack peaks and program code size */ - static coap_packet_t message[1]; /* this way the packet can be treated as pointer as usual */ - static coap_packet_t response[1]; - static coap_transaction_t *transaction = NULL; - - if(uip_newdata()) { - - PRINTF("receiving UDP datagram from: "); - PRINT6ADDR(&UIP_IP_BUF->srcipaddr); - PRINTF(":%u\n Length: %u\n", uip_ntohs(UIP_UDP_BUF->srcport), - uip_datalen()); - - erbium_status_code = - coap_parse_message(message, uip_appdata, uip_datalen()); - - if(erbium_status_code == NO_ERROR) { - - /*TODO duplicates suppression, if required by application */ - - PRINTF(" Parsed: v %u, t %u, tkl %u, c %u, mid %u\n", message->version, - message->type, message->token_len, message->code, message->mid); - PRINTF(" URL: %.*s\n", message->uri_path_len, message->uri_path); - PRINTF(" Payload: %.*s\n", message->payload_len, message->payload); - - /* handle requests */ - if(message->code >= COAP_GET && message->code <= COAP_DELETE) { - - /* use transaction buffer for response to confirmable request */ - if((transaction = - coap_new_transaction(message->mid, &UIP_IP_BUF->srcipaddr, - UIP_UDP_BUF->srcport))) { - uint32_t block_num = 0; - uint16_t block_size = COAP_MAX_BLOCK_SIZE; - uint32_t block_offset = 0; - int32_t new_offset = 0; - - /* prepare response */ - if(message->type == COAP_TYPE_CON) { - /* reliable CON requests are answered with an ACK */ - coap_init_message(response, COAP_TYPE_ACK, CONTENT_2_05, - message->mid); - } else { - /* unreliable NON requests are answered with a NON as well */ - coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05, - coap_get_mid()); - /* mirror token */ - } if(message->token_len) { - coap_set_token(response, message->token, message->token_len); - /* get offset for blockwise transfers */ - } - if(coap_get_header_block2 - (message, &block_num, NULL, &block_size, &block_offset)) { - PRINTF("Blockwise: block request %lu (%u/%u) @ %lu bytes\n", - block_num, block_size, COAP_MAX_BLOCK_SIZE, block_offset); - block_size = MIN(block_size, COAP_MAX_BLOCK_SIZE); - new_offset = block_offset; - } + static coap_message_t message[1]; /* this way the message can be treated as pointer as usual */ + static coap_message_t response[1]; + coap_transaction_t *transaction = NULL; + coap_handler_status_t status; + + coap_status_code = coap_parse_message(message, payload, payload_length); + coap_set_src_endpoint(message, src); + + if(coap_status_code == NO_ERROR) { + + /*TODO duplicates suppression, if required by application */ + + LOG_DBG(" Parsed: v %u, t %u, tkl %u, c %u, mid %u\n", message->version, + message->type, message->token_len, message->code, message->mid); + LOG_DBG(" URL:"); + LOG_DBG_COAP_STRING(message->uri_path, message->uri_path_len); + LOG_DBG_("\n"); + LOG_DBG(" Payload: "); + LOG_DBG_COAP_STRING((const char *)message->payload, message->payload_len); + LOG_DBG_("\n"); + + /* handle requests */ + if(message->code >= COAP_GET && message->code <= COAP_DELETE) { + + /* use transaction buffer for response to confirmable request */ + if((transaction = coap_new_transaction(message->mid, src))) { + uint32_t block_num = 0; + uint16_t block_size = COAP_MAX_BLOCK_SIZE; + uint32_t block_offset = 0; + int32_t new_offset = 0; + + /* prepare response */ + if(message->type == COAP_TYPE_CON) { + /* reliable CON requests are answered with an ACK */ + coap_init_message(response, COAP_TYPE_ACK, CONTENT_2_05, + message->mid); + } else { + /* unreliable NON requests are answered with a NON as well */ + coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05, + coap_get_mid()); + /* mirror token */ + } + if(message->token_len) { + coap_set_token(response, message->token, message->token_len); + /* get offset for blockwise transfers */ + } + if(coap_get_header_block2 + (message, &block_num, NULL, &block_size, &block_offset)) { + LOG_DBG("Blockwise: block request %"PRIu32" (%u/%u) @ %"PRIu32" bytes\n", + block_num, block_size, COAP_MAX_BLOCK_SIZE, block_offset); + block_size = MIN(block_size, COAP_MAX_BLOCK_SIZE); + new_offset = block_offset; + } + + if(new_offset < 0) { + LOG_DBG("Blockwise: block request offset overflow\n"); + coap_status_code = BAD_OPTION_4_02; + coap_error_message = "BlockOutOfScope"; + status = COAP_HANDLER_STATUS_CONTINUE; + } else { + /* call CoAP framework and check if found and allowed */ + status = call_service(message, response, + transaction->message + COAP_MAX_HEADER_SIZE, + block_size, &new_offset); + } + + if(status != COAP_HANDLER_STATUS_CONTINUE) { + + if(coap_status_code == NO_ERROR) { + + /* TODO coap_handle_blockwise(request, response, start_offset, end_offset); */ - /* invoke resource handler */ - if(service_cbk) { - - /* call REST framework and check if found and allowed */ - if(service_cbk - (message, response, transaction->packet + COAP_MAX_HEADER_SIZE, - block_size, &new_offset)) { - - if(erbium_status_code == NO_ERROR) { - - /* TODO coap_handle_blockwise(request, response, start_offset, end_offset); */ - - /* resource is unaware of Block1 */ - if(IS_OPTION(message, COAP_OPTION_BLOCK1) - && response->code < BAD_REQUEST_4_00 - && !IS_OPTION(response, COAP_OPTION_BLOCK1)) { - PRINTF("Block1 NOT IMPLEMENTED\n"); - - erbium_status_code = NOT_IMPLEMENTED_5_01; - coap_error_message = "NoBlock1Support"; - - /* client requested Block2 transfer */ - } else if(IS_OPTION(message, COAP_OPTION_BLOCK2)) { - - /* unchanged new_offset indicates that resource is unaware of blockwise transfer */ - if(new_offset == block_offset) { - PRINTF - ("Blockwise: unaware resource with payload length %u/%u\n", - response->payload_len, block_size); - if(block_offset >= response->payload_len) { - PRINTF - ("handle_incoming_data(): block_offset >= response->payload_len\n"); - - response->code = BAD_OPTION_4_02; - coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */ - } else { - coap_set_header_block2(response, block_num, - response->payload_len - - block_offset > block_size, - block_size); - coap_set_payload(response, - response->payload + block_offset, - MIN(response->payload_len - - block_offset, block_size)); - } /* if(valid offset) */ - - /* resource provides chunk-wise data */ + /* resource is unaware of Block1 */ + if(coap_is_option(message, COAP_OPTION_BLOCK1) + && response->code < BAD_REQUEST_4_00 + && !coap_is_option(response, COAP_OPTION_BLOCK1)) { + LOG_DBG("Block1 NOT IMPLEMENTED\n"); + + coap_status_code = NOT_IMPLEMENTED_5_01; + coap_error_message = "NoBlock1Support"; + + /* client requested Block2 transfer */ + } else if(coap_is_option(message, COAP_OPTION_BLOCK2)) { + + /* unchanged new_offset indicates that resource is unaware of blockwise transfer */ + if(new_offset == block_offset) { + LOG_DBG("Blockwise: unaware resource with payload length %u/%u\n", + response->payload_len, block_size); + if(block_offset >= response->payload_len) { + LOG_DBG("handle_incoming_data(): block_offset >= response->payload_len\n"); + + response->code = BAD_OPTION_4_02; + coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */ } else { - PRINTF("Blockwise: blockwise resource, new offset %ld\n", - new_offset); coap_set_header_block2(response, block_num, - new_offset != -1 - || response->payload_len > - block_size, block_size); - - if(response->payload_len > block_size) { - coap_set_payload(response, response->payload, - block_size); - } - } /* if(resource aware of blockwise) */ - - /* Resource requested Block2 transfer */ - } else if(new_offset != 0) { - PRINTF - ("Blockwise: no block option for blockwise resource, using block size %u\n", - COAP_MAX_BLOCK_SIZE); - - coap_set_header_block2(response, 0, new_offset != -1, - COAP_MAX_BLOCK_SIZE); - coap_set_payload(response, response->payload, - MIN(response->payload_len, - COAP_MAX_BLOCK_SIZE)); - } /* blockwise transfer handling */ - } /* no errors/hooks */ - /* successful service callback */ - /* serialize response */ - } - if(erbium_status_code == NO_ERROR) { - if((transaction->packet_len = coap_serialize_message(response, - transaction-> - packet)) == - 0) { - erbium_status_code = PACKET_SERIALIZATION_ERROR; - } + response->payload_len - + block_offset > block_size, + block_size); + coap_set_payload(response, + response->payload + block_offset, + MIN(response->payload_len - + block_offset, block_size)); + } /* if(valid offset) */ + + /* resource provides chunk-wise data */ + } else { + LOG_DBG("Blockwise: blockwise resource, new offset %"PRId32"\n", + new_offset); + coap_set_header_block2(response, block_num, + new_offset != -1 + || response->payload_len > + block_size, block_size); + + if(response->payload_len > block_size) { + coap_set_payload(response, response->payload, + block_size); + } + } /* if(resource aware of blockwise) */ + + /* Resource requested Block2 transfer */ + } else if(new_offset != 0) { + LOG_DBG("Blockwise: no block option for blockwise resource, using block size %u\n", + COAP_MAX_BLOCK_SIZE); + + coap_set_header_block2(response, 0, new_offset != -1, + COAP_MAX_BLOCK_SIZE); + coap_set_payload(response, response->payload, + MIN(response->payload_len, + COAP_MAX_BLOCK_SIZE)); + } /* blockwise transfer handling */ + } /* no errors/hooks */ + /* successful service callback */ + /* serialize response */ + } + if(coap_status_code == NO_ERROR) { + if((transaction->message_len = coap_serialize_message(response, + transaction-> + message)) == + 0) { + coap_status_code = PACKET_SERIALIZATION_ERROR; } - } else { - erbium_status_code = NOT_IMPLEMENTED_5_01; - coap_error_message = "NoServiceCallbck"; /* no 'a' to fit into 16 bytes */ - } /* if(service callback) */ - } else { - erbium_status_code = SERVICE_UNAVAILABLE_5_03; - coap_error_message = "NoFreeTraBuffer"; - } /* if(transaction buffer) */ - - /* handle responses */ + } } else { + coap_status_code = SERVICE_UNAVAILABLE_5_03; + coap_error_message = "NoFreeTraBuffer"; + } /* if(transaction buffer) */ - if(message->type == COAP_TYPE_CON && message->code == 0) { - PRINTF("Received Ping\n"); - erbium_status_code = PING_RESPONSE; - } else if(message->type == COAP_TYPE_ACK) { - /* transactions are closed through lookup below */ - PRINTF("Received ACK\n"); - } else if(message->type == COAP_TYPE_RST) { - PRINTF("Received RST\n"); - /* cancel possible subscriptions */ - coap_remove_observer_by_mid(&UIP_IP_BUF->srcipaddr, - UIP_UDP_BUF->srcport, message->mid); - } + /* handle responses */ + } else { - if((transaction = coap_get_transaction_by_mid(message->mid))) { - /* free transaction memory before callback, as it may create a new transaction */ - restful_response_handler callback = transaction->callback; - void *callback_data = transaction->callback_data; + if(message->type == COAP_TYPE_CON && message->code == 0) { + LOG_INFO("Received Ping\n"); + coap_status_code = PING_RESPONSE; + } else if(message->type == COAP_TYPE_ACK) { + /* transactions are closed through lookup below */ + LOG_DBG("Received ACK\n"); + } else if(message->type == COAP_TYPE_RST) { + LOG_INFO("Received RST\n"); + /* cancel possible subscriptions */ + coap_remove_observer_by_mid(src, message->mid); + } - coap_clear_transaction(transaction); + if((transaction = coap_get_transaction_by_mid(message->mid))) { + /* free transaction memory before callback, as it may create a new transaction */ + coap_resource_response_handler_t callback = transaction->callback; + void *callback_data = transaction->callback_data; - /* check if someone registered for the response */ - if(callback) { - callback(callback_data, message); - } + coap_clear_transaction(transaction); + + /* check if someone registered for the response */ + if(callback) { + callback(callback_data, message); } - /* if(ACKed transaction) */ - transaction = NULL; + } + /* if(ACKed transaction) */ + transaction = NULL; #if COAP_OBSERVE_CLIENT - /* if observe notification */ - if((message->type == COAP_TYPE_CON || message->type == COAP_TYPE_NON) - && IS_OPTION(message, COAP_OPTION_OBSERVE)) { - PRINTF("Observe [%u]\n", message->observe); - coap_handle_notification(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, - message); - } + /* if observe notification */ + if((message->type == COAP_TYPE_CON || message->type == COAP_TYPE_NON) + && coap_is_option(message, COAP_OPTION_OBSERVE)) { + LOG_DBG("Observe [%"PRId32"]\n", message->observe); + coap_handle_notification(src, message); + } #endif /* COAP_OBSERVE_CLIENT */ - } /* request or response */ - } /* parsed correctly */ + } /* request or response */ + } /* parsed correctly */ /* if(parsed correctly) */ - if(erbium_status_code == NO_ERROR) { - if(transaction) { - coap_send_transaction(transaction); - } - } else if(erbium_status_code == MANUAL_RESPONSE) { - PRINTF("Clearing transaction for manual response"); - coap_clear_transaction(transaction); - } else { - coap_message_type_t reply_type = COAP_TYPE_ACK; - - PRINTF("ERROR %u: %s\n", erbium_status_code, coap_error_message); - coap_clear_transaction(transaction); - - if(erbium_status_code == PING_RESPONSE) { - erbium_status_code = 0; - reply_type = COAP_TYPE_RST; - } else if(erbium_status_code >= 192) { - /* set to sendable error code */ - erbium_status_code = INTERNAL_SERVER_ERROR_5_00; - /* reuse input buffer for error message */ - } - coap_init_message(message, reply_type, erbium_status_code, - message->mid); - coap_set_payload(message, coap_error_message, - strlen(coap_error_message)); - coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, - uip_appdata, coap_serialize_message(message, - uip_appdata)); + if(coap_status_code == NO_ERROR) { + if(transaction) { + coap_send_transaction(transaction); + } + } else if(coap_status_code == MANUAL_RESPONSE) { + LOG_DBG("Clearing transaction for manual response"); + coap_clear_transaction(transaction); + } else { + coap_message_type_t reply_type = COAP_TYPE_ACK; + + LOG_WARN("ERROR %u: %s\n", coap_status_code, coap_error_message); + coap_clear_transaction(transaction); + + if(coap_status_code == PING_RESPONSE) { + coap_status_code = 0; + reply_type = COAP_TYPE_RST; + } else if(coap_status_code >= 192) { + /* set to sendable error code */ + coap_status_code = INTERNAL_SERVER_ERROR_5_00; + /* reuse input buffer for error message */ } + coap_init_message(message, reply_type, coap_status_code, + message->mid); + coap_set_payload(message, coap_error_message, + strlen(coap_error_message)); + coap_sendto(src, payload, coap_serialize_message(message, payload)); } /* if(new data) */ - return erbium_status_code; + return coap_status_code; } /*---------------------------------------------------------------------------*/ void -coap_init_engine(void) +coap_engine_init(void) { - process_start(&coap_engine, NULL); + /* avoid initializing twice */ + if(is_initialized) { + LOG_DBG("already running - double initialization?\n"); + return; + } + is_initialized = 1; + + LOG_INFO("Starting CoAP engine...\n"); + + list_init(coap_handlers); + list_init(coap_resource_services); + + coap_activate_resource(&res_well_known_core, ".well-known/core"); + + coap_transport_init(); + coap_init_connection(); } /*---------------------------------------------------------------------------*/ +/** + * \brief Makes a resource available under the given URI path + * \param resource A pointer to a resource implementation + * \param path The URI path string for this resource + * + * The resource implementation must be imported first using the + * extern keyword. The build system takes care of compiling every + * *.c file in the ./resources/ sub-directory (see example Makefile). + */ void -coap_set_service_callback(service_callback_t callback) +coap_activate_resource(coap_resource_t *resource, const char *path) { - service_cbk = callback; -} -/*---------------------------------------------------------------------------*/ -rest_resource_flags_t -coap_get_rest_method(void *packet) -{ - return (rest_resource_flags_t)(1 << - (((coap_packet_t *)packet)->code - 1)); + coap_periodic_resource_t *periodic; + resource->url = path; + list_add(coap_resource_services, resource); + + LOG_INFO("Activating: %s\n", resource->url); + + /* Only add periodic resources with a periodic_handler and a period > 0. */ + if(resource->flags & IS_PERIODIC && resource->periodic + && resource->periodic->periodic_handler + && resource->periodic->period) { + LOG_DBG("Periodic resource: %p (%s)\n", resource->periodic, path); + periodic = resource->periodic; + coap_timer_set_callback(&periodic->periodic_timer, process_callback); + coap_timer_set_user_data(&periodic->periodic_timer, resource); + coap_timer_set(&periodic->periodic_timer, periodic->period); + } } /*---------------------------------------------------------------------------*/ -/*- Server Part -------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ - -/* the discover resource is automatically included for CoAP */ -extern resource_t res_well_known_core; -#ifdef WITH_DTLS -extern resource_t res_dtls; -#endif /*---------------------------------------------------------------------------*/ -PROCESS_THREAD(coap_engine, ev, data) +/*- Internal API ------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +coap_resource_t * +coap_get_first_resource(void) { - PROCESS_BEGIN(); - PRINTF("Starting %s receiver...\n", coap_rest_implementation.name); - - rest_activate_resource(&res_well_known_core, ".well-known/core"); - - coap_register_as_transaction_handler(); - coap_init_connection(SERVER_LISTEN_PORT); - - while(1) { - PROCESS_YIELD(); - - if(ev == tcpip_event) { - coap_receive(); - } else if(ev == PROCESS_EVENT_TIMER) { - /* retransmissions are handled here */ - coap_check_transactions(); - } - } /* while (1) */ - - PROCESS_END(); + return list_head(coap_resource_services); } /*---------------------------------------------------------------------------*/ -/*- Client Part -------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -void -coap_blocking_request_callback(void *callback_data, void *response) +coap_resource_t * +coap_get_next_resource(coap_resource_t *resource) { - struct request_state_t *state = (struct request_state_t *)callback_data; - - state->response = (coap_packet_t *)response; - process_poll(state->process); + return list_item_next(resource); } /*---------------------------------------------------------------------------*/ -PT_THREAD(coap_blocking_request - (struct request_state_t *state, process_event_t ev, - uip_ipaddr_t *remote_ipaddr, uint16_t remote_port, - coap_packet_t *request, - blocking_response_handler request_callback)) +static int +invoke_coap_resource_service(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t buffer_size, + int32_t *offset) { - PT_BEGIN(&state->pt); - - static uint8_t more; - static uint32_t res_block; - static uint8_t block_error; - - state->block_num = 0; - state->response = NULL; - state->process = PROCESS_CURRENT(); - - more = 0; - res_block = 0; - block_error = 0; - - do { - request->mid = coap_get_mid(); - if((state->transaction = coap_new_transaction(request->mid, remote_ipaddr, - remote_port))) { - state->transaction->callback = coap_blocking_request_callback; - state->transaction->callback_data = state; - - if(state->block_num > 0) { - coap_set_header_block2(request, state->block_num, 0, - REST_MAX_CHUNK_SIZE); - } - state->transaction->packet_len = coap_serialize_message(request, - state-> - transaction-> - packet); - - coap_send_transaction(state->transaction); - PRINTF("Requested #%lu (MID %u)\n", state->block_num, request->mid); - - PT_YIELD_UNTIL(&state->pt, ev == PROCESS_EVENT_POLL); - - if(!state->response) { - PRINTF("Server not responding\n"); - PT_EXIT(&state->pt); - } - - coap_get_header_block2(state->response, &res_block, &more, NULL, NULL); - - PRINTF("Received #%lu%s (%u bytes)\n", res_block, more ? "+" : "", - state->response->payload_len); - - if(res_block == state->block_num) { - request_callback(state->response); - ++(state->block_num); + uint8_t found = 0; + uint8_t allowed = 1; + + coap_resource_t *resource = NULL; + const char *url = NULL; + int url_len, res_url_len; + + url_len = coap_get_header_uri_path(request, &url); + for(resource = list_head(coap_resource_services); + resource; resource = resource->next) { + + /* if the web service handles that kind of requests and urls matches */ + res_url_len = strlen(resource->url); + if((url_len == res_url_len + || (url_len > res_url_len + && (resource->flags & HAS_SUB_RESOURCES) + && url[res_url_len] == '/')) + && strncmp(resource->url, url, res_url_len) == 0) { + coap_resource_flags_t method = coap_get_method_type(request); + found = 1; + + LOG_INFO("/%s, method %u, resource->flags %u\n", resource->url, + (uint16_t)method, resource->flags); + + if((method & METHOD_GET) && resource->get_handler != NULL) { + /* call handler function */ + resource->get_handler(request, response, buffer, buffer_size, offset); + } else if((method & METHOD_POST) && resource->post_handler != NULL) { + /* call handler function */ + resource->post_handler(request, response, buffer, buffer_size, + offset); + } else if((method & METHOD_PUT) && resource->put_handler != NULL) { + /* call handler function */ + resource->put_handler(request, response, buffer, buffer_size, offset); + } else if((method & METHOD_DELETE) && resource->delete_handler != NULL) { + /* call handler function */ + resource->delete_handler(request, response, buffer, buffer_size, + offset); } else { - PRINTF("WRONG BLOCK %lu/%lu\n", res_block, state->block_num); - ++block_error; + allowed = 0; + coap_set_status_code(response, METHOD_NOT_ALLOWED_4_05); } - } else { - PRINTF("Could not allocate transaction buffer"); - PT_EXIT(&state->pt); + break; } - } while(more && block_error < COAP_MAX_ATTEMPTS); - - PT_END(&state->pt); + } + if(!found) { + coap_set_status_code(response, NOT_FOUND_4_04); + } else if(allowed) { + /* final handler for special flags */ + if(resource->flags & IS_OBSERVABLE) { + coap_observe_handler(resource, request, response); + } + } + return found & allowed; } /*---------------------------------------------------------------------------*/ -/*- REST Engine Interface ---------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -const struct rest_implementation coap_rest_implementation = { - "CoAP-18", - - coap_init_engine, - coap_set_service_callback, - - coap_get_header_uri_path, - coap_get_rest_method, - coap_set_status_code, - - coap_get_header_content_format, - coap_set_header_content_format, - coap_get_header_accept, - coap_get_header_size2, - coap_set_header_size2, - coap_get_header_max_age, - coap_set_header_max_age, - coap_set_header_etag, - coap_get_header_if_match, - coap_get_header_if_none_match, - coap_get_header_uri_host, - coap_set_header_location_path, - - coap_get_payload, - coap_set_payload, - - coap_get_header_uri_query, - coap_get_query_variable, - coap_get_post_variable, - - coap_notify_observers, - coap_observe_handler, - - { - CONTENT_2_05, - CREATED_2_01, - CHANGED_2_04, - DELETED_2_02, - VALID_2_03, - BAD_REQUEST_4_00, - UNAUTHORIZED_4_01, - BAD_OPTION_4_02, - FORBIDDEN_4_03, - NOT_FOUND_4_04, - METHOD_NOT_ALLOWED_4_05, - NOT_ACCEPTABLE_4_06, - REQUEST_ENTITY_TOO_LARGE_4_13, - UNSUPPORTED_MEDIA_TYPE_4_15, - INTERNAL_SERVER_ERROR_5_00, - NOT_IMPLEMENTED_5_01, - BAD_GATEWAY_5_02, - SERVICE_UNAVAILABLE_5_03, - GATEWAY_TIMEOUT_5_04, - PROXYING_NOT_SUPPORTED_5_05 - }, - - { - TEXT_PLAIN, - TEXT_XML, - TEXT_CSV, - TEXT_HTML, - IMAGE_GIF, - IMAGE_JPEG, - IMAGE_PNG, - IMAGE_TIFF, - AUDIO_RAW, - VIDEO_RAW, - APPLICATION_LINK_FORMAT, - APPLICATION_XML, - APPLICATION_OCTET_STREAM, - APPLICATION_RDF_XML, - APPLICATION_SOAP_XML, - APPLICATION_ATOM_XML, - APPLICATION_XMPP_XML, - APPLICATION_EXI, - APPLICATION_FASTINFOSET, - APPLICATION_SOAP_FASTINFOSET, - APPLICATION_JSON, - APPLICATION_X_OBIX_BINARY +/* This callback occurs when t is expired */ +static void +process_callback(coap_timer_t *t) +{ + coap_resource_t *resource; + resource = coap_timer_get_user_data(t); + if(resource != NULL && (resource->flags & IS_PERIODIC) + && resource->periodic != NULL && resource->periodic->period) { + LOG_DBG("Periodic: timer expired for /%s (period: %"PRIu32")\n", + resource->url, resource->periodic->period); + + if(!is_initialized) { + /* CoAP has not yet been initialized. */ + } else if(resource->periodic->periodic_handler) { + /* Call the periodic_handler function. */ + resource->periodic->periodic_handler(); + } + + coap_timer_set(t, resource->periodic->period); } -}; +} /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-engine.h b/os/net/app-layer/coap/coap-engine.h index 8b3ae1d2c4dd2484d67a90ff4bd462d43ace6ab4..140ed0211b94231ef9d6ccd041546bd4d4a1e9eb 100644 --- a/os/net/app-layer/coap/coap-engine.h +++ b/os/net/app-layer/coap/coap-engine.h @@ -31,56 +31,148 @@ /** * \file - * CoAP implementation for the REST Engine. + * CoAP engine implementation. * \author * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ -#ifndef ER_COAP_ENGINE_H_ -#define ER_COAP_ENGINE_H_ +/** + * \addtogroup coap + * @{ + */ + +#ifndef COAP_ENGINE_H_ +#define COAP_ENGINE_H_ + +typedef struct coap_resource_s coap_resource_t; +typedef struct coap_periodic_resource_s coap_periodic_resource_t; -#include "pt.h" #include "coap.h" -#include "coap-transactions.h" -#include "coap-observe.h" -#include "coap-separate.h" -#include "coap-observe-client.h" +#include "coap-timer.h" -#define SERVER_LISTEN_PORT UIP_HTONS(COAP_SERVER_PORT) +typedef enum { + COAP_HANDLER_STATUS_CONTINUE, + COAP_HANDLER_STATUS_PROCESSED +} coap_handler_status_t; -typedef coap_packet_t rest_request_t; -typedef coap_packet_t rest_response_t; +typedef coap_handler_status_t +(* coap_handler_callback_t)(coap_message_t *request, + coap_message_t *response, + uint8_t *buffer, uint16_t buffer_size, + int32_t *offset); -void coap_init_engine(void); +typedef struct coap_handler coap_handler_t; +struct coap_handler { + coap_handler_t *next; + coap_handler_callback_t handler; +}; + +#define COAP_HANDLER(name, handler) \ + coap_handler_t name = { NULL, handler } + +void coap_add_handler(coap_handler_t *handler); +void coap_remove_handler(coap_handler_t *handler); + +void coap_engine_init(void); + +int coap_receive(const coap_endpoint_t *src, + uint8_t *payload, uint16_t payload_length); + +coap_handler_status_t coap_call_handlers(coap_message_t *request, + coap_message_t *response, + uint8_t *buffer, + uint16_t buffer_size, + int32_t *offset); /*---------------------------------------------------------------------------*/ -/*- Client Part -------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -struct request_state_t { - struct pt pt; - struct process *process; - coap_transaction_t *transaction; - coap_packet_t *response; - uint32_t block_num; +/* signatures of handler functions */ +typedef void (* coap_resource_handler_t)(coap_message_t *request, + coap_message_t *response, + uint8_t *buffer, + uint16_t preferred_size, + int32_t *offset); +typedef void (* coap_resource_periodic_handler_t)(void); +typedef void (* coap_resource_response_handler_t)(void *data, + coap_message_t *response); +typedef void (* coap_resource_trigger_handler_t)(void); + +/* data structure representing a resource in CoAP */ +struct coap_resource_s { + coap_resource_t *next; /* for LIST, points to next resource defined */ + const char *url; /*handled URL */ + coap_resource_flags_t flags; /* handled CoAP methods */ + const char *attributes; /* link-format attributes */ + coap_resource_handler_t get_handler; /* handler function */ + coap_resource_handler_t post_handler; /* handler function */ + coap_resource_handler_t put_handler; /* handler function */ + coap_resource_handler_t delete_handler; /* handler function */ + union { + coap_periodic_resource_t *periodic; /* special data depending on flags */ + coap_resource_trigger_handler_t trigger; + coap_resource_trigger_handler_t resume; + }; }; -typedef void (*blocking_response_handler)(void *response); - -PT_THREAD(coap_blocking_request - (struct request_state_t *state, process_event_t ev, - uip_ipaddr_t *remote_ipaddr, uint16_t remote_port, - coap_packet_t *request, - blocking_response_handler request_callback)); - -#define COAP_BLOCKING_REQUEST(server_addr, server_port, request, chunk_handler) \ - { \ - static struct request_state_t request_state; \ - PT_SPAWN(process_pt, &request_state.pt, \ - coap_blocking_request(&request_state, ev, \ - server_addr, server_port, \ - request, chunk_handler) \ - ); \ - } +struct coap_periodic_resource_s { + uint32_t period; + coap_timer_t periodic_timer; + const coap_resource_periodic_handler_t periodic_handler; +}; + +/* + * Macro to define a CoAP resource. + * Resources are statically defined for the sake of efficiency and better memory management. + */ +#define RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \ + coap_resource_t name = { NULL, NULL, NO_FLAGS, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } } + +#define PARENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \ + coap_resource_t name = { NULL, NULL, HAS_SUB_RESOURCES, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } } + +#define SEPARATE_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, resume_handler) \ + coap_resource_t name = { NULL, NULL, IS_SEPARATE, attributes, get_handler, post_handler, put_handler, delete_handler, { .resume = resume_handler } } + +#define EVENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, event_handler) \ + coap_resource_t name = { NULL, NULL, IS_OBSERVABLE, attributes, get_handler, post_handler, put_handler, delete_handler, { .trigger = event_handler } } + +/* + * Macro to define a periodic resource. + * The corresponding [name]_periodic_handler() function will be called every period. + * For instance polling a sensor and publishing a changed value to subscribed clients would be done there. + */ +#define PERIODIC_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, period, periodic_handler) \ + static coap_periodic_resource_t periodic_##name = { period, { 0 }, periodic_handler }; \ + coap_resource_t name = { NULL, NULL, IS_OBSERVABLE | IS_PERIODIC, attributes, get_handler, post_handler, put_handler, delete_handler, { .periodic = &periodic_##name } } + /*---------------------------------------------------------------------------*/ +/** + * + * \brief Resources wanted to be accessible should be activated with the following code. + * \param resource + * A CoAP resource defined through the RESOURCE macros. + * \param path + * The local URI path where to provide the resource. + */ +void coap_activate_resource(coap_resource_t *resource, const char *path); +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the first of registered CoAP resources. + * \return The first registered CoAP resource or NULL if none exists. + */ +coap_resource_t *coap_get_first_resource(void); +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the next registered CoAP resource. + * \return The next resource or NULL if no more exists. + */ +coap_resource_t *coap_get_next_resource(coap_resource_t *resource); +/*---------------------------------------------------------------------------*/ + +#include "coap-transactions.h" +#include "coap-observe.h" +#include "coap-separate.h" +#include "coap-observe-client.h" +#include "coap-transport.h" -#endif /* ER_COAP_ENGINE_H_ */ +#endif /* COAP_ENGINE_H_ */ +/** @} */ diff --git a/os/services/lwm2m/oma-tlv-writer.c b/os/net/app-layer/coap/coap-keystore-simple.c similarity index 57% rename from os/services/lwm2m/oma-tlv-writer.c rename to os/net/app-layer/coap/coap-keystore-simple.c index 2f26a69f64ff3212b18dad5516ae7c22be9fdd27..1eb8737e9b998dbcc6b8560511c1cac444801de0 100644 --- a/os/services/lwm2m/oma-tlv-writer.c +++ b/os/net/app-layer/coap/coap-keystore-simple.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2017, RISE SICS AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,62 +28,70 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * \addtogroup oma-lwm2m - * @{ - * - */ - /** * \file - * Implementation of the Contiki OMA LWM2M TLV writer + * A simple keystore with fixed credentials. * \author - * Joakim Eriksson <joakime@sics.se> * Niclas Finne <nfi@sics.se> + * Joakim Eriksson <joakime@sics.se> */ -#include "lwm2m-object.h" -#include "oma-tlv.h" -/*---------------------------------------------------------------------------*/ -static size_t -write_boolean_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, - int value) -{ - return oma_tlv_write_int32(ctx->resource_id, value != 0 ? 1 : 0, - outbuf, outlen); -} +/** + * \addtogroup coap-keystore + * @{ + */ + +#include "coap-endpoint.h" +#include "coap-keystore.h" +#include <string.h> + +#ifdef WITH_DTLS +#ifdef COAP_DTLS_PSK_DEFAULT_IDENTITY +#ifdef COAP_DTLS_PSK_DEFAULT_KEY /*---------------------------------------------------------------------------*/ -static size_t -write_int_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, - int32_t value) +static int +get_default_psk_info(const coap_endpoint_t *address_info, + coap_keystore_psk_entry_t *info) { - return oma_tlv_write_int32(ctx->resource_id, value, outbuf, outlen); + if(info != NULL) { + if(info->identity == NULL || info->identity_len == 0) { + /* Identity requested */ + info->identity = (uint8_t *)COAP_DTLS_PSK_DEFAULT_IDENTITY; + info->identity_len = strlen(COAP_DTLS_PSK_DEFAULT_IDENTITY); + return 1; + } + if(info->identity_len != strlen(COAP_DTLS_PSK_DEFAULT_IDENTITY) || + memcmp(info->identity, COAP_DTLS_PSK_DEFAULT_IDENTITY, + info->identity_len) != 0) { + /* Identity not matching */ + return 0; + } + info->key = (uint8_t *)COAP_DTLS_PSK_DEFAULT_KEY; + info->key_len = strlen(COAP_DTLS_PSK_DEFAULT_KEY); + return 1; + } + return 0; } +static const coap_keystore_t simple_key_store = { + .coap_get_psk_info = get_default_psk_info +}; /*---------------------------------------------------------------------------*/ -static size_t -write_float32fix_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, - size_t outlen, int32_t value, int bits) -{ - return oma_tlv_write_float32(ctx->resource_id, value, bits, outbuf, outlen); -} +#endif /* COAP_DTLS_PSK_DEFAULT_KEY */ +#endif /* COAP_DTLS_PSK_DEFAULT_IDENTITY */ +#endif /* WITH_DTLS */ /*---------------------------------------------------------------------------*/ -static size_t -write_string_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, - const char *value, size_t stringlen) +void +coap_keystore_simple_init(void) { - oma_tlv_t tlv; - tlv.type = OMA_TLV_TYPE_RESOURCE; - tlv.value = (uint8_t *) value; - tlv.length = (uint32_t) stringlen; - tlv.id = ctx->resource_id; - return oma_tlv_write(&tlv, outbuf, outlen); +#ifdef WITH_DTLS +#ifdef COAP_DTLS_PSK_DEFAULT_IDENTITY +#ifdef COAP_DTLS_PSK_DEFAULT_KEY + + coap_set_keystore(&simple_key_store); + +#endif /* COAP_DTLS_PSK_DEFAULT_KEY */ +#endif /* COAP_DTLS_PSK_DEFAULT_IDENTITY */ +#endif /* WITH_DTLS */ } /*---------------------------------------------------------------------------*/ -const lwm2m_writer_t oma_tlv_writer = { - write_int_tlv, - write_string_tlv, - write_float32fix_tlv, - write_boolean_tlv -}; -/*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/net/app-layer/coap/coap-keystore-simple.h b/os/net/app-layer/coap/coap-keystore-simple.h new file mode 100644 index 0000000000000000000000000000000000000000..2252002d46b2b16a6bd7a5e5767b2c49a042c8d6 --- /dev/null +++ b/os/net/app-layer/coap/coap-keystore-simple.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017, RISE SICS AB. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * A simple keystore with fixed credentials. + * \author + * Niclas Finne <nfi@sics.se> + * Joakim Eriksson <joakime@sics.se> + */ + +/** + * \addtogroup coap-keystore + * @{ + */ + +#ifndef COAP_KEYSTORE_SIMPLE_H_ +#define COAP_KEYSTORE_SIMPLE_H_ + +/** + * \brief Registers a simple CoAP DTLS keystore with fixed pre-shared key + * credentials. + * + * The credentials can be configured in project-conf.h as shown in the + * following example: + * + * ~~~~~~~~~~~~~~~{.c} + * #define COAP_DTLS_PSK_DEFAULT_IDENTITY "user" + * #define COAP_DTLS_PSK_DEFAULT_KEY "password" + * ~~~~~~~~~~~~~~~ + */ +void coap_keystore_simple_init(void); + +#endif /* COAP_KEYSTORE_SIMPLE_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-keystore.h b/os/net/app-layer/coap/coap-keystore.h new file mode 100644 index 0000000000000000000000000000000000000000..6a3763d5aaf8fadfc0a113add8edc7919b64217e --- /dev/null +++ b/os/net/app-layer/coap/coap-keystore.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2017, RISE SICS + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + */ + +/** + * \file + * API for CoAP keystore + * \author + * Niclas Finne <nfi@sics.se> + * Joakim Eriksson <joakime@sics.se> + */ + +/** + * \addtogroup coap + * @{ + * + * \defgroup coap-keystore CoAP keystore API + * @{ + * + * The CoAP keystore API defines a common interface for retrieving + * authorization information for CoAP/DTLS. + */ + +#ifndef COAP_KEYSTORE_H_ +#define COAP_KEYSTORE_H_ + +#include "coap-endpoint.h" + +/** + * The structure of a CoAP pre-shared key info. + */ +typedef struct { + const uint8_t *identity_hint; + uint16_t identity_hint_len; + const uint8_t *identity; + uint16_t identity_len; + const uint8_t *key; + uint16_t key_len; +} coap_keystore_psk_entry_t; + +/** + * The structure of a CoAP keystore. + * + * The keystore implementation provides a function callback for each type of + * authorization supported. The API currently only specifies a function + * callback for pre-shared keys. + */ +typedef struct { + int (* coap_get_psk_info)(const coap_endpoint_t *address_info, + coap_keystore_psk_entry_t *info); +} coap_keystore_t; + +/** + * \brief Set the CoAP keystore to use by CoAP. + * \param keystore A pointer to a CoAP keystore. + */ +void coap_set_keystore(const coap_keystore_t *keystore); + +#endif /* COAP_KEYSTORE_H_ */ +/** @} */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-log.c b/os/net/app-layer/coap/coap-log.c new file mode 100644 index 0000000000000000000000000000000000000000..36f3bc01655d6503bf3b5aeb4437b2e9b568e3a0 --- /dev/null +++ b/os/net/app-layer/coap/coap-log.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017, RISE SICS. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * Log support for CoAP + * \author + * Niclas Finne <niclas.finne@ri.se> + * Joakim Eriksson <joakim.eriksson@ri.se> + */ + +/** + * \addtogroup coap + * @{ + */ + +#include "coap-log.h" +/*---------------------------------------------------------------------------*/ +void +coap_log_string(const char *text, size_t len) +{ + int i; + if(text == NULL) { + LOG_OUTPUT("(NULL STR)"); + return; + } + + for(i = 0; i < len && *text != '\0'; i++, text++) { + LOG_OUTPUT("%c", *text); + } +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-log.h b/os/net/app-layer/coap/coap-log.h new file mode 100644 index 0000000000000000000000000000000000000000..2e6a0a359d427fd98a43974cf0914902c9dc47da --- /dev/null +++ b/os/net/app-layer/coap/coap-log.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017, RISE SICS. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * Log support for CoAP + * \author + * Niclas Finne <niclas.finne@ri.se> + * Joakim Eriksson <joakim.eriksson@ri.se> + */ + +/** + * \addtogroup coap + * @{ + */ + +#ifndef COAP_LOG_H_ +#define COAP_LOG_H_ + +#include "contiki.h" + +#ifdef COAP_LOG_CONF_PATH +#include COAP_LOG_CONF_PATH +#else /* COAP_LOG_CONF_PATH */ +#include "sys/log.h" +#endif /* COAP_LOG_CONF_PATH */ + +#include "coap-endpoint.h" + +/* CoAP endpoint */ +#define LOG_COAP_EP(level, endpoint) do { \ + if(level <= (LOG_LEVEL)) { \ + coap_endpoint_log(endpoint); \ + } \ + } while (0) + +#define LOG_ERR_COAP_EP(endpoint) LOG_COAP_EP(LOG_LEVEL_ERR, endpoint) +#define LOG_WARN_COAP_EP(endpoint) LOG_COAP_EP(LOG_LEVEL_WARN, endpoint) +#define LOG_INFO_COAP_EP(endpoint) LOG_COAP_EP(LOG_LEVEL_INFO, endpoint) +#define LOG_DBG_COAP_EP(endpoint) LOG_COAP_EP(LOG_LEVEL_DBG, endpoint) + +/* CoAP strings */ +#define LOG_COAP_STRING(level, text, len) do { \ + if(level <= (LOG_LEVEL)) { \ + coap_log_string(text, len); \ + } \ + } while (0) + +#define LOG_ERR_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_ERR, text, len) +#define LOG_WARN_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_WARN, text, len) +#define LOG_INFO_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_INFO, text, len) +#define LOG_DBG_COAP_STRING(text, len) LOG_COAP_STRING(LOG_LEVEL_DBG, text, len) + +/** + * \brief Logs a CoAP string that has a length but might not be 0-terminated. + * \param text The CoAP string + * \param len The number of characters in the CoAP string + */ +void coap_log_string(const char *text, size_t len); + +#endif /* COAP_LOG_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-observe-client.c b/os/net/app-layer/coap/coap-observe-client.c index 84edec98e195a189e65268fef9937758ff80ae93..a273084944415c1da978773fce1c1a28711ac0c4 100644 --- a/os/net/app-layer/coap/coap-observe-client.c +++ b/os/net/app-layer/coap/coap-observe-client.c @@ -37,57 +37,42 @@ * Daniele Alessandrelli <daniele.alessandrelli@gmail.com> */ -#include <stdio.h> -#include <string.h> +/** + * \addtogroup coap + * @{ + */ #include "coap.h" #include "coap-observe-client.h" +#include "sys/cc.h" +#include "lib/memb.h" +#include "lib/list.h" +#include <stdio.h> +#include <string.h> /* Compile this code only if client-side support for CoAP Observe is required */ #if COAP_OBSERVE_CLIENT -#define DEBUG 1 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:" \ - "%02x%02x:%02x%02x:%02x%02x:%02x%02x]", \ - ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], \ - ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], \ - ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], \ - ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], \ - ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], \ - ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], \ - ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], \ - ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", \ - (lladdr)->addr[0], (lladdr)->addr[1], \ - (lladdr)->addr[2], (lladdr)->addr[3], \ - (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap" +#define LOG_LEVEL LOG_LEVEL_COAP MEMB(obs_subjects_memb, coap_observee_t, COAP_MAX_OBSERVEES); LIST(obs_subjects_list); /*----------------------------------------------------------------------------*/ static size_t -get_token(void *packet, const uint8_t **token) +get_token(coap_message_t *coap_pkt, const uint8_t **token) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - *token = coap_pkt->token; return coap_pkt->token_len; } /*----------------------------------------------------------------------------*/ static int -set_token(void *packet, const uint8_t *token, size_t token_len) +set_token(coap_message_t *coap_pkt, const uint8_t *token, size_t token_len) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->token_len = MIN(COAP_TOKEN_LEN, token_len); memcpy(coap_pkt->token, token, coap_pkt->token_len); @@ -95,7 +80,7 @@ set_token(void *packet, const uint8_t *token, size_t token_len) } /*----------------------------------------------------------------------------*/ coap_observee_t * -coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port, +coap_obs_add_observee(const coap_endpoint_t *endpoint, const uint8_t *token, size_t token_len, const char *url, notification_callback_t notification_callback, void *data) @@ -103,20 +88,18 @@ coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port, coap_observee_t *o; /* Remove existing observe relationship, if any. */ - coap_obs_remove_observee_by_url(addr, port, url); + coap_obs_remove_observee_by_url(endpoint, url); o = memb_alloc(&obs_subjects_memb); if(o) { o->url = url; - uip_ipaddr_copy(&o->addr, addr); - o->port = port; + coap_endpoint_copy(&o->endpoint, endpoint); o->token_len = token_len; memcpy(o->token, token, token_len); /* o->last_mid = 0; */ o->notification_callback = notification_callback; o->data = data; - /* stimer_set(&o->refresh_timer, COAP_OBSERVING_REFRESH_INTERVAL); */ - PRINTF("Adding obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0], - o->token[1]); + LOG_DBG("Adding obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0], + o->token[1]); list_add(obs_subjects_list, o); } @@ -126,8 +109,8 @@ coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port, void coap_obs_remove_observee(coap_observee_t *o) { - PRINTF("Removing obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0], - o->token[1]); + LOG_DBG("Removing obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0], + o->token[1]); memb_free(&obs_subjects_memb, o); list_remove(obs_subjects_list, o); } @@ -139,7 +122,7 @@ coap_get_obs_subject_by_token(const uint8_t *token, size_t token_len) for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs; obs = obs->next) { - PRINTF("Looking for token 0x%02X%02X\n", token[0], token[1]); + LOG_DBG("Looking for token 0x%02X%02X\n", token[0], token[1]); if(obs->token_len == token_len && memcmp(obs->token, token, token_len) == 0) { return obs; @@ -150,7 +133,7 @@ coap_get_obs_subject_by_token(const uint8_t *token, size_t token_len) } /*----------------------------------------------------------------------------*/ int -coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port, +coap_obs_remove_observee_by_token(const coap_endpoint_t *endpoint, uint8_t *token, size_t token_len) { int removed = 0; @@ -158,9 +141,8 @@ coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port, for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs; obs = obs->next) { - PRINTF("Remove check Token 0x%02X%02X\n", token[0], token[1]); - if(uip_ipaddr_cmp(&obs->addr, addr) - && obs->port == port + LOG_DBG("Remove check Token 0x%02X%02X\n", token[0], token[1]); + if(coap_endpoint_cmp(&obs->endpoint, endpoint) && obs->token_len == token_len && memcmp(obs->token, token, token_len) == 0) { coap_obs_remove_observee(obs); @@ -171,7 +153,7 @@ coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port, } /*----------------------------------------------------------------------------*/ int -coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port, +coap_obs_remove_observee_by_url(const coap_endpoint_t *endpoint, const char *url) { int removed = 0; @@ -179,9 +161,8 @@ coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port, for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs; obs = obs->next) { - PRINTF("Remove check URL %s\n", url); - if(uip_ipaddr_cmp(&obs->addr, addr) - && obs->port == port + LOG_DBG("Remove check URL %s\n", url); + if(coap_endpoint_cmp(&obs->endpoint, endpoint) && (obs->url == url || memcmp(obs->url, url, strlen(obs->url)) == 0)) { coap_obs_remove_observee(obs); removed++; @@ -191,34 +172,31 @@ coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port, } /*----------------------------------------------------------------------------*/ static void -simple_reply(coap_message_type_t type, uip_ip6addr_t *addr, uint16_t port, - coap_packet_t *notification) +simple_reply(coap_message_type_t type, const coap_endpoint_t *endpoint, + coap_message_t *notification) { - static coap_packet_t response[1]; + static coap_message_t response[1]; size_t len; coap_init_message(response, type, NO_ERROR, notification->mid); - len = coap_serialize_message(response, uip_appdata); - coap_send_message(addr, port, uip_appdata, len); + len = coap_serialize_message(response, coap_databuf()); + coap_sendto(endpoint, coap_databuf(), len); } /*----------------------------------------------------------------------------*/ static coap_notification_flag_t -classify_notification(void *response, int first) +classify_notification(coap_message_t *response, int first) { - coap_packet_t *pkt; - - pkt = (coap_packet_t *)response; - if(!pkt) { - PRINTF("no response\n"); + if(!response) { + LOG_DBG("no response\n"); return NO_REPLY_FROM_SERVER; } - PRINTF("server replied\n"); - if(!IS_RESPONSE_CODE_2_XX(pkt)) { - PRINTF("error response code\n"); + LOG_DBG("server replied\n"); + if(!IS_RESPONSE_CODE_2_XX(response)) { + LOG_DBG("error response code\n"); return ERROR_RESPONSE_CODE; } - if(!IS_OPTION(pkt, COAP_OPTION_OBSERVE)) { - PRINTF("server does not support observe\n"); + if(!coap_is_option(response, COAP_OPTION_OBSERVE)) { + LOG_DBG("server does not support observe\n"); return OBSERVE_NOT_SUPPORTED; } if(first) { @@ -228,35 +206,33 @@ classify_notification(void *response, int first) } /*----------------------------------------------------------------------------*/ void -coap_handle_notification(uip_ipaddr_t *addr, uint16_t port, - coap_packet_t *notification) +coap_handle_notification(const coap_endpoint_t *endpoint, + coap_message_t *notification) { - coap_packet_t *pkt; const uint8_t *token; int token_len; coap_observee_t *obs; coap_notification_flag_t flag; uint32_t observe; - PRINTF("coap_handle_notification()\n"); - pkt = (coap_packet_t *)notification; - token_len = get_token(pkt, &token); - PRINTF("Getting token\n"); + LOG_DBG("coap_handle_notification()\n"); + token_len = get_token(notification, &token); + LOG_DBG("Getting token\n"); if(0 == token_len) { - PRINTF("Error while handling coap observe notification: " - "no token in message\n"); + LOG_DBG("Error while handling coap observe notification: " + "no token in message\n"); return; } - PRINTF("Getting observee info\n"); + LOG_DBG("Getting observee info\n"); obs = coap_get_obs_subject_by_token(token, token_len); if(NULL == obs) { - PRINTF("Error while handling coap observe notification: " - "no matching token found\n"); - simple_reply(COAP_TYPE_RST, addr, port, notification); + LOG_DBG("Error while handling coap observe notification: " + "no matching token found\n"); + simple_reply(COAP_TYPE_RST, endpoint, notification); return; } if(notification->type == COAP_TYPE_CON) { - simple_reply(COAP_TYPE_ACK, addr, port, notification); + simple_reply(COAP_TYPE_ACK, endpoint, notification); } if(obs->notification_callback != NULL) { flag = classify_notification(notification, 0); @@ -265,7 +241,7 @@ coap_handle_notification(uip_ipaddr_t *addr, uint16_t port, if(flag == NOTIFICATION_OK) { coap_get_header_observe(notification, &observe); if(observe == obs->last_observe) { - PRINTF("Discarding duplicate\n"); + LOG_DBG("Discarding duplicate\n"); return; } obs->last_observe = observe; @@ -275,13 +251,13 @@ coap_handle_notification(uip_ipaddr_t *addr, uint16_t port, } /*----------------------------------------------------------------------------*/ static void -handle_obs_registration_response(void *data, void *response) +handle_obs_registration_response(void *data, coap_message_t *response) { coap_observee_t *obs; notification_callback_t notification_callback; coap_notification_flag_t flag; - PRINTF("handle_obs_registration_response(): "); + LOG_DBG("handle_obs_registration_response()\n"); obs = (coap_observee_t *)data; notification_callback = obs->notification_callback; flag = classify_notification(response, 1); @@ -305,11 +281,11 @@ coap_generate_token(uint8_t **token_ptr) } /*----------------------------------------------------------------------------*/ coap_observee_t * -coap_obs_request_registration(uip_ipaddr_t *addr, uint16_t port, char *uri, +coap_obs_request_registration(const coap_endpoint_t *endpoint, char *uri, notification_callback_t notification_callback, void *data) { - coap_packet_t request[1]; + coap_message_t request[1]; coap_transaction_t *t; uint8_t *token; uint8_t token_len; @@ -321,22 +297,23 @@ coap_obs_request_registration(uip_ipaddr_t *addr, uint16_t port, char *uri, coap_set_header_observe(request, 0); token_len = coap_generate_token(&token); set_token(request, token, token_len); - t = coap_new_transaction(request->mid, addr, port); + t = coap_new_transaction(request->mid, endpoint); if(t) { - obs = coap_obs_add_observee(addr, port, (uint8_t *)token, token_len, uri, + obs = coap_obs_add_observee(endpoint, (uint8_t *)token, token_len, uri, notification_callback, data); if(obs) { t->callback = handle_obs_registration_response; t->callback_data = obs; - t->packet_len = coap_serialize_message(request, t->packet); + t->message_len = coap_serialize_message(request, t->message); coap_send_transaction(t); } else { - PRINTF("Could not allocate obs_subject resource buffer"); + LOG_DBG("Could not allocate obs_subject resource buffer\n"); coap_clear_transaction(t); } } else { - PRINTF("Could not allocate transaction buffer"); + LOG_DBG("Could not allocate transaction buffer\n"); } return obs; } #endif /* COAP_OBSERVE_CLIENT */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-observe-client.h b/os/net/app-layer/coap/coap-observe-client.h index c0ea0c5a2259aa0108dbbe6f1d035fdfa36ff999..79625caffeede0b722ccdfcb2ae86ee82d605627 100644 --- a/os/net/app-layer/coap/coap-observe-client.h +++ b/os/net/app-layer/coap/coap-observe-client.h @@ -37,6 +37,11 @@ * Daniele Alessandrelli <daniele.alessandrelli@gmail.com> */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_OBSERVING_CLIENT_H_ #define COAP_OBSERVING_CLIENT_H_ @@ -79,8 +84,7 @@ typedef void (*notification_callback_t)(coap_observee_t *subject, struct coap_observee_s { coap_observee_t *next; /* for LIST */ - uip_ipaddr_t addr; - uint16_t port; + coap_endpoint_t endpoint; const char *url; uint8_t token_len; uint8_t token[COAP_TOKEN_LEN]; @@ -90,7 +94,7 @@ struct coap_observee_s { }; /*----------------------------------------------------------------------------*/ -coap_observee_t *coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port, +coap_observee_t *coap_obs_add_observee(const coap_endpoint_t *endpoint, const uint8_t *token, size_t token_len, const char *url, notification_callback_t @@ -101,17 +105,17 @@ void coap_obs_remove_observee(coap_observee_t *o); coap_observee_t *coap_obs_get_observee_by_token(const uint8_t *token, size_t token_len); -int coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port, +int coap_obs_remove_observee_by_token(const coap_endpoint_t *endpoint, uint8_t *token, size_t token_len); -int coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port, +int coap_obs_remove_observee_by_url(const coap_endpoint_t *endpoint, const char *url); -void coap_handle_notification(uip_ipaddr_t *addr, uint16_t port, - coap_packet_t *notification); +void coap_handle_notification(const coap_endpoint_t *endpoint, + coap_message_t *notification); -coap_observee_t *coap_obs_request_registration(uip_ipaddr_t *addr, - uint16_t port, char *uri, +coap_observee_t *coap_obs_request_registration(const coap_endpoint_t *endpoint, + char *uri, notification_callback_t notification_callback, void *data); @@ -119,3 +123,4 @@ coap_observee_t *coap_obs_request_registration(uip_ipaddr_t *addr, uint8_t coap_generate_token(uint8_t **token_ptr); #endif /* COAP_OBSERVING_CLIENT_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-observe.c b/os/net/app-layer/coap/coap-observe.c index 2237e4e25c7c0a63acfdb7f778c89e123665cf63..83f5edf4a4a09559ca53b26d546203b0fb476fdc 100644 --- a/os/net/app-layer/coap/coap-observe.c +++ b/os/net/app-layer/coap/coap-observe.c @@ -36,21 +36,22 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +/** + * \addtogroup coap + * @{ + */ + #include <stdio.h> #include <string.h> #include "coap-observe.h" +#include "coap-engine.h" +#include "lib/memb.h" +#include "lib/list.h" -#define DEBUG 0 -#if DEBUG -#include <stdio.h> -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap" +#define LOG_LEVEL LOG_LEVEL_COAP /*---------------------------------------------------------------------------*/ MEMB(observers_memb, coap_observer_t, COAP_MAX_OBSERVERS); @@ -59,11 +60,11 @@ LIST(observers_list); /*- Internal API ------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ static coap_observer_t * -add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, +add_observer(const coap_endpoint_t *endpoint, const uint8_t *token, size_t token_len, const char *uri, int uri_len) { /* Remove existing observe relationship, if any. */ - coap_remove_observer_by_uri(addr, port, uri); + coap_remove_observer_by_uri(endpoint, uri); coap_observer_t *o = memb_alloc(&observers_memb); @@ -74,15 +75,14 @@ add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, } memcpy(o->url, uri, max); o->url[max] = 0; - uip_ipaddr_copy(&o->addr, addr); - o->port = port; + coap_endpoint_copy(&o->endpoint, endpoint); o->token_len = token_len; memcpy(o->token, token, token_len); o->last_mid = 0; - PRINTF("Adding observer (%u/%u) for /%s [0x%02X%02X]\n", - list_length(observers_list) + 1, COAP_MAX_OBSERVERS, - o->url, o->token[0], o->token[1]); + LOG_INFO("Adding observer (%u/%u) for /%s [0x%02X%02X]\n", + list_length(observers_list) + 1, COAP_MAX_OBSERVERS, + o->url, o->token[0], o->token[1]); list_add(observers_list, o); } @@ -94,25 +94,25 @@ add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, void coap_remove_observer(coap_observer_t *o) { - PRINTF("Removing observer for /%s [0x%02X%02X]\n", o->url, o->token[0], - o->token[1]); + LOG_INFO("Removing observer for /%s [0x%02X%02X]\n", o->url, o->token[0], + o->token[1]); memb_free(&observers_memb, o); list_remove(observers_list, o); } /*---------------------------------------------------------------------------*/ int -coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port) +coap_remove_observer_by_client(const coap_endpoint_t *endpoint) { int removed = 0; coap_observer_t *obs = NULL; + LOG_DBG("Remove check client "); + LOG_DBG_COAP_EP(endpoint); + LOG_DBG_("\n"); for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { - PRINTF("Remove check client "); - PRINT6ADDR(addr); - PRINTF(":%u\n", port); - if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port) { + if(coap_endpoint_cmp(&obs->endpoint, endpoint)) { coap_remove_observer(obs); removed++; } @@ -121,7 +121,7 @@ coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port) } /*---------------------------------------------------------------------------*/ int -coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, +coap_remove_observer_by_token(const coap_endpoint_t *endpoint, uint8_t *token, size_t token_len) { int removed = 0; @@ -129,8 +129,8 @@ coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { - PRINTF("Remove check Token 0x%02X%02X\n", token[0], token[1]); - if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port + LOG_DBG("Remove check Token 0x%02X%02X\n", token[0], token[1]); + if(coap_endpoint_cmp(&obs->endpoint, endpoint) && obs->token_len == token_len && memcmp(obs->token, token, token_len) == 0) { coap_remove_observer(obs); @@ -141,7 +141,7 @@ coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, } /*---------------------------------------------------------------------------*/ int -coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port, +coap_remove_observer_by_uri(const coap_endpoint_t *endpoint, const char *uri) { int removed = 0; @@ -149,9 +149,9 @@ coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port, for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { - PRINTF("Remove check URL %p\n", uri); - if((addr == NULL - || (uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port)) + LOG_DBG("Remove check URL %p\n", uri); + if((endpoint == NULL + || (coap_endpoint_cmp(&obs->endpoint, endpoint))) && (obs->url == uri || memcmp(obs->url, uri, strlen(obs->url)) == 0)) { coap_remove_observer(obs); removed++; @@ -161,15 +161,15 @@ coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port, } /*---------------------------------------------------------------------------*/ int -coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, uint16_t mid) +coap_remove_observer_by_mid(const coap_endpoint_t *endpoint, uint16_t mid) { int removed = 0; coap_observer_t *obs = NULL; for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { - PRINTF("Remove check MID %u\n", mid); - if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port + LOG_DBG("Remove check MID %u\n", mid); + if(coap_endpoint_cmp(&obs->endpoint, endpoint) && obs->last_mid == mid) { coap_remove_observer(obs); removed++; @@ -181,29 +181,40 @@ coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, uint16_t mid) /*- Notification ------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ void -coap_notify_observers(resource_t *resource) +coap_notify_observers(coap_resource_t *resource) { coap_notify_observers_sub(resource, NULL); } +/* Can be used either for sub - or when there is not resource - just + a handler */ void -coap_notify_observers_sub(resource_t *resource, const char *subpath) +coap_notify_observers_sub(coap_resource_t *resource, const char *subpath) { /* build notification */ - coap_packet_t notification[1]; /* this way the packet can be treated as pointer as usual */ - coap_packet_t request[1]; /* this way the packet can be treated as pointer as usual */ + coap_message_t notification[1]; /* this way the message can be treated as pointer as usual */ + coap_message_t request[1]; /* this way the message can be treated as pointer as usual */ coap_observer_t *obs = NULL; int url_len, obs_url_len; char url[COAP_OBSERVER_URL_LEN]; + uint8_t sub_ok = 0; - url_len = strlen(resource->url); - strncpy(url, resource->url, COAP_OBSERVER_URL_LEN - 1); - if(url_len < COAP_OBSERVER_URL_LEN - 1 && subpath != NULL) { - strncpy(&url[url_len], subpath, COAP_OBSERVER_URL_LEN - url_len - 1); + if(resource != NULL) { + url_len = strlen(resource->url); + strncpy(url, resource->url, COAP_OBSERVER_URL_LEN - 1); + if(url_len < COAP_OBSERVER_URL_LEN - 1 && subpath != NULL) { + strncpy(&url[url_len], subpath, COAP_OBSERVER_URL_LEN - url_len - 1); + } + } else if(subpath != NULL) { + strncpy(url, subpath, COAP_OBSERVER_URL_LEN - 1); + } else { + /* No resource, no subpath */ + return; } + /* Ensure url is null terminated because strncpy does not guarantee this */ url[COAP_OBSERVER_URL_LEN - 1] = '\0'; /* url now contains the notify URL that needs to match the observer */ - PRINTF("Observe: Notification from %s\n", url); + LOG_INFO("Notification from %s\n", url); coap_init_message(notification, COAP_TYPE_NON, CONTENT_2_05, 0); /* create a "fake" request for the URI */ @@ -212,30 +223,35 @@ coap_notify_observers_sub(resource_t *resource, const char *subpath) /* iterate over observers */ url_len = strlen(url); + /* Assumes lazy evaluation... */ + sub_ok = (resource == NULL) || (resource->flags & HAS_SUB_RESOURCES); for(obs = (coap_observer_t *)list_head(observers_list); obs; obs = obs->next) { obs_url_len = strlen(obs->url); /* Do a match based on the parent/sub-resource match so that it is possible to do parent-node observe */ + + /***** TODO fix here so that we handle the notofication correctly ******/ + /* All the new-style ... is assuming that the URL might be within */ if((obs_url_len == url_len || (obs_url_len > url_len - && (resource->flags & HAS_SUB_RESOURCES) + && sub_ok && obs->url[url_len] == '/')) && strncmp(url, obs->url, url_len) == 0) { coap_transaction_t *transaction = NULL; /*TODO implement special transaction for CON, sharing the same buffer to allow for more observers */ - if((transaction = coap_new_transaction(coap_get_mid(), &obs->addr, obs->port))) { + if((transaction = coap_new_transaction(coap_get_mid(), &obs->endpoint))) { if(obs->obs_counter % COAP_OBSERVE_REFRESH_INTERVAL == 0) { - PRINTF(" Force Confirmable for\n"); + LOG_DBG(" Force Confirmable for\n"); notification->type = COAP_TYPE_CON; } - PRINTF(" Observer "); - PRINT6ADDR(&obs->addr); - PRINTF(":%u\n", obs->port); + LOG_DBG(" Observer "); + LOG_DBG_COAP_EP(&obs->endpoint); + LOG_DBG_("\n"); /* update last MID for RST matching */ obs->last_mid = transaction->mid; @@ -243,9 +259,23 @@ coap_notify_observers_sub(resource_t *resource, const char *subpath) /* prepare response */ notification->mid = transaction->mid; - resource->get_handler(request, notification, - transaction->packet + COAP_MAX_HEADER_SIZE, - REST_MAX_CHUNK_SIZE, NULL); + int32_t new_offset = 0; + + /* Either old style get_handler or the full handler */ + if(coap_call_handlers(request, notification, transaction->message + + COAP_MAX_HEADER_SIZE, COAP_MAX_CHUNK_SIZE, + &new_offset) > 0) { + LOG_DBG("Notification on new handlers\n"); + } else { + if(resource != NULL) { + resource->get_handler(request, notification, + transaction->message + COAP_MAX_HEADER_SIZE, + COAP_MAX_CHUNK_SIZE, &new_offset); + } else { + /* What to do here? */ + notification->code = BAD_REQUEST_4_00; + } + } if(notification->code < BAD_REQUEST_4_00) { coap_set_header_observe(notification, (obs->obs_counter)++); @@ -254,8 +284,19 @@ coap_notify_observers_sub(resource_t *resource, const char *subpath) } coap_set_token(notification, obs->token, obs->token_len); - transaction->packet_len = - coap_serialize_message(notification, transaction->packet); + if(new_offset != 0) { + coap_set_header_block2(notification, + 0, + new_offset != -1, + COAP_MAX_BLOCK_SIZE); + coap_set_payload(notification, + notification->payload, + MIN(notification->payload_len, + COAP_MAX_BLOCK_SIZE)); + } + + transaction->message_len = + coap_serialize_message(notification, transaction->message); coap_send_transaction(transaction); } @@ -264,16 +305,21 @@ coap_notify_observers_sub(resource_t *resource, const char *subpath) } /*---------------------------------------------------------------------------*/ void -coap_observe_handler(resource_t *resource, void *request, void *response) +coap_observe_handler(coap_resource_t *resource, coap_message_t *coap_req, + coap_message_t *coap_res) { - coap_packet_t *const coap_req = (coap_packet_t *)request; - coap_packet_t *const coap_res = (coap_packet_t *)response; + const coap_endpoint_t *src_ep; coap_observer_t *obs; + LOG_DBG("CoAP observer handler rsc: %d\n", resource != NULL); + if(coap_req->code == COAP_GET && coap_res->code < 128) { /* GET request and response without error code */ - if(IS_OPTION(coap_req, COAP_OPTION_OBSERVE)) { - if(coap_req->observe == 0) { - obs = add_observer(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, + if(coap_is_option(coap_req, COAP_OPTION_OBSERVE)) { + src_ep = coap_get_src_endpoint(coap_req); + if(src_ep == NULL) { + /* No source endpoint, can not add */ + } else if(coap_req->observe == 0) { + obs = add_observer(src_ep, coap_req->token, coap_req->token_len, coap_req->uri_path, coap_req->uri_path_len); if(obs) { @@ -300,11 +346,11 @@ coap_observe_handler(resource_t *resource, void *request, void *response) } else if(coap_req->observe == 1) { /* remove client if it is currently observe */ - coap_remove_observer_by_token(&UIP_IP_BUF->srcipaddr, - UIP_UDP_BUF->srcport, coap_req->token, - coap_req->token_len); + coap_remove_observer_by_token(src_ep, + coap_req->token, coap_req->token_len); } } } } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-observe.h b/os/net/app-layer/coap/coap-observe.h index 7ff2bb502f2eaae92ab47b4a2769f0181b4be698..c276522c5e6e2bb07803e6d71c5199aa0f5f45b5 100644 --- a/os/net/app-layer/coap/coap-observe.h +++ b/os/net/app-layer/coap/coap-observe.h @@ -36,53 +36,49 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_OBSERVE_H_ #define COAP_OBSERVE_H_ #include "coap.h" #include "coap-transactions.h" -#include "stimer.h" +#include "coap-engine.h" #define COAP_OBSERVER_URL_LEN 20 -typedef struct coap_observable { - uint32_t observe_clock; - struct stimer orphan_timer; - list_t observers; - coap_packet_t notification; - uint8_t buffer[COAP_MAX_PACKET_SIZE + 1]; -} coap_observable_t; - typedef struct coap_observer { struct coap_observer *next; /* for LIST */ char url[COAP_OBSERVER_URL_LEN]; - uip_ipaddr_t addr; - uint16_t port; + coap_endpoint_t endpoint; uint8_t token_len; uint8_t token[COAP_TOKEN_LEN]; uint16_t last_mid; int32_t obs_counter; - struct etimer retrans_timer; + coap_timer_t retrans_timer; uint8_t retrans_counter; } coap_observer_t; -list_t coap_get_observers(void); void coap_remove_observer(coap_observer_t *o); -int coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port); -int coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, +int coap_remove_observer_by_client(const coap_endpoint_t *ep); +int coap_remove_observer_by_token(const coap_endpoint_t *ep, uint8_t *token, size_t token_len); -int coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port, +int coap_remove_observer_by_uri(const coap_endpoint_t *ep, const char *uri); -int coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, +int coap_remove_observer_by_mid(const coap_endpoint_t *ep, uint16_t mid); -void coap_notify_observers(resource_t *resource); -void coap_notify_observers_sub(resource_t *resource, const char *subpath); +void coap_notify_observers(coap_resource_t *resource); +void coap_notify_observers_sub(coap_resource_t *resource, const char *subpath); -void coap_observe_handler(resource_t *resource, void *request, - void *response); +void coap_observe_handler(coap_resource_t *resource, coap_message_t *request, + coap_message_t *response); #endif /* COAP_OBSERVE_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-res-well-known-core.c b/os/net/app-layer/coap/coap-res-well-known-core.c index 117e362ab4e3661fc317fb8f3d0386e129955976..ebaae8fd45e00e9ea82881def7ac898e96947bc5 100644 --- a/os/net/app-layer/coap/coap-res-well-known-core.c +++ b/os/net/app-layer/coap/coap-res-well-known-core.c @@ -36,20 +36,19 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ -#include <string.h> -#include "coap-engine.h" +/** + * \addtogroup coap + * @{ + */ -#define DEBUG 0 -#if DEBUG +#include "coap-engine.h" +#include <string.h> #include <stdio.h> -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap" +#define LOG_LEVEL LOG_LEVEL_COAP #define ADD_CHAR_IF_POSSIBLE(char) \ if(strpos >= *offset && bufpos < preferred_size) { \ @@ -67,7 +66,7 @@ + (*offset - (int32_t)strpos > 0 ? \ *offset - (int32_t)strpos : 0)); \ if(bufpos op preferred_size) { \ - PRINTF("res: BREAK at %s (%p)\n", string, resource); \ + LOG_DBG("BREAK at %s (%p)\n", string, resource); \ break; \ } \ } \ @@ -76,14 +75,15 @@ /*---------------------------------------------------------------------------*/ /*- Resource Handlers -------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -void -well_known_core_get_handler(void *request, void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +static void +well_known_core_get_handler(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t preferred_size, + int32_t *offset) { size_t strpos = 0; /* position in overall string (which is larger than the buffer) */ size_t bufpos = 0; /* position within buffer (bytes written) */ size_t tmplen = 0; - resource_t *resource = NULL; + coap_resource_t *resource = NULL; #if COAP_LINK_FORMAT_FILTERING /* For filtering. */ @@ -101,7 +101,9 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer, ++value; len -= strlen(filter) + 1; - PRINTF("Filter %s = %.*s\n", filter, len, value); + LOG_DBG("Filter %s = ", filter); + LOG_DBG_COAP_STRING(value, len); + LOG_DBG_("\n"); if(strcmp(filter, "href") == 0 && value[0] == '/') { ++value; @@ -111,10 +113,10 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer, lastchar = value[len - 1]; value[len - 1] = '\0'; } -#endif +#endif /* COAP_LINK_FORMAT_FILTERING */ - for(resource = (resource_t *)list_head(rest_get_resources()); resource; - resource = resource->next) { + for(resource = coap_get_first_resource(); resource; + resource = coap_get_next_resource(resource)) { #if COAP_LINK_FORMAT_FILTERING /* Filtering */ if(len) { @@ -135,7 +137,7 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer, end = strchr(attrib, '"'); } - PRINTF("Filter: res has attrib %s (%s)\n", attrib, value); + LOG_DBG("Filter: res has attrib %s (%s)\n", attrib, value); found = attrib; while((found = strstr(found, value)) != NULL) { if(found > end) { @@ -150,17 +152,17 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer, if(found == NULL) { continue; } - PRINTF("Filter: res has prefix %s\n", found); + LOG_DBG("Filter: res has prefix %s\n", found); if(lastchar != '*' && (found[len] != '"' && found[len] != ' ' && found[len] != '\0')) { continue; } - PRINTF("Filter: res has match\n"); + LOG_DBG("Filter: res has match\n"); } #endif - PRINTF("res: /%s (%p)\npos: s%zu, o%ld, b%zu\n", resource->url, resource, - strpos, (long)*offset, bufpos); + LOG_DBG("/%s (%p)\npos: s%zu, o%ld, b%zu\n", resource->url, resource, + strpos, (long)*offset, bufpos); if(strpos > 0) { ADD_CHAR_IF_POSSIBLE(','); @@ -177,28 +179,30 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer, /* buffer full, but resource not completed yet; or: do not break if resource exactly fills buffer. */ if(bufpos > preferred_size && strpos - bufpos > *offset) { - PRINTF("res: BREAK at %s (%p)\n", resource->url, resource); + LOG_DBG("BREAK at %s (%p)\n", resource->url, resource); break; } } if(bufpos > 0) { - PRINTF("BUF %zu: %.*s\n", bufpos, (int)bufpos, (char *)buffer); + LOG_DBG("BUF %zu: ", bufpos); + LOG_DBG_COAP_STRING((char *)buffer, bufpos); + LOG_DBG_("\n"); coap_set_payload(response, buffer, bufpos); coap_set_header_content_format(response, APPLICATION_LINK_FORMAT); } else if(strpos > 0) { - PRINTF("well_known_core_handler(): bufpos<=0\n"); + LOG_DBG("well_known_core_handler(): bufpos<=0\n"); coap_set_status_code(response, BAD_OPTION_4_02); coap_set_payload(response, "BlockOutOfScope", 15); } if(resource == NULL) { - PRINTF("res: DONE\n"); + LOG_DBG("DONE\n"); *offset = -1; } else { - PRINTF("res: MORE at %s (%p)\n", resource->url, resource); + LOG_DBG("MORE at %s (%p)\n", resource->url, resource); *offset += preferred_size; } } @@ -206,3 +210,4 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer, RESOURCE(res_well_known_core, "ct=40", well_known_core_get_handler, NULL, NULL, NULL); /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-separate.c b/os/net/app-layer/coap/coap-separate.c index 03f95c41139e094f151669f652979cc9ef091206..7eb5e5675933befe93594f5a16c82e061b7167f0 100644 --- a/os/net/app-layer/coap/coap-separate.c +++ b/os/net/app-layer/coap/coap-separate.c @@ -36,23 +36,21 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ -#include "sys/cc.h" -#include <stdio.h> -#include <string.h> +/** + * \addtogroup coap + * @{ + */ + +#include "coap.h" #include "coap-separate.h" #include "coap-transactions.h" +#include "sys/cc.h" +#include <string.h> -#define DEBUG 0 -#if DEBUG -#include <stdio.h> -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap" +#define LOG_LEVEL LOG_LEVEL_COAP /*---------------------------------------------------------------------------*/ /*- Separate Response API ---------------------------------------------------*/ @@ -69,13 +67,13 @@ void coap_separate_reject() { /* TODO: Accept string pointer for custom error message */ - erbium_status_code = SERVICE_UNAVAILABLE_5_03; + coap_status_code = SERVICE_UNAVAILABLE_5_03; coap_error_message = "AlreadyInUse"; } /*----------------------------------------------------------------------------*/ /** * \brief Initiate a separate response with an empty ACK - * \param request The request to accept + * \param coap_req The request to accept * \param separate_store A pointer to the data structure that will store the * relevant information for the response * @@ -85,29 +83,33 @@ coap_separate_reject() * then retry later. */ void -coap_separate_accept(void *request, coap_separate_t *separate_store) +coap_separate_accept(coap_message_t *coap_req, coap_separate_t *separate_store) { - coap_packet_t *const coap_req = (coap_packet_t *)request; coap_transaction_t *const t = coap_get_transaction_by_mid(coap_req->mid); - PRINTF("Separate ACCEPT: /%.*s MID %u\n", coap_req->uri_path_len, - coap_req->uri_path, coap_req->mid); + LOG_DBG("Separate ACCEPT: /"); + LOG_DBG_COAP_STRING(coap_req->uri_path, coap_req->uri_path_len); + LOG_DBG_(" MID %u\n", coap_req->mid); if(t) { /* send separate ACK for CON */ if(coap_req->type == COAP_TYPE_CON) { - coap_packet_t ack[1]; + coap_message_t ack[1]; + const coap_endpoint_t *ep; - /* ACK with empty code (0) */ - coap_init_message(ack, COAP_TYPE_ACK, 0, coap_req->mid); - /* serializing into IPBUF: Only overwrites header parts that are already parsed into the request struct */ - coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, - (uip_appdata), coap_serialize_message(ack, - uip_appdata)); + ep = coap_get_src_endpoint(coap_req); + if(ep == NULL) { + LOG_ERR("ERROR: no endpoint in request\n"); + } else { + /* ACK with empty code (0) */ + coap_init_message(ack, COAP_TYPE_ACK, 0, coap_req->mid); + /* serializing into IPBUF: Only overwrites header parts that are already parsed into the request struct */ + coap_sendto(ep, coap_databuf(), + coap_serialize_message(ack, coap_databuf())); + } } - /* store remote address */ - uip_ipaddr_copy(&separate_store->addr, &t->addr); - separate_store->port = t->port; + /* store remote endpoint address */ + coap_endpoint_copy(&separate_store->endpoint, &t->endpoint); /* store correct response type */ separate_store->type = @@ -124,15 +126,15 @@ coap_separate_accept(void *request, coap_separate_t *separate_store) separate_store->block2_size = coap_req->block2_size > 0 ? MIN(COAP_MAX_BLOCK_SIZE, coap_req->block2_size) : COAP_MAX_BLOCK_SIZE; /* signal the engine to skip automatic response and clear transaction by engine */ - erbium_status_code = MANUAL_RESPONSE; + coap_status_code = MANUAL_RESPONSE; } else { - PRINTF("ERROR: Response transaction for separate request not found!\n"); - erbium_status_code = INTERNAL_SERVER_ERROR_5_00; + LOG_ERR("ERROR: Response transaction for separate request not found!\n"); + coap_status_code = INTERNAL_SERVER_ERROR_5_00; } } /*----------------------------------------------------------------------------*/ void -coap_separate_resume(void *response, coap_separate_t *separate_store, +coap_separate_resume(coap_message_t *response, coap_separate_t *separate_store, uint8_t code) { coap_init_message(response, separate_store->type, code, @@ -147,3 +149,4 @@ coap_separate_resume(void *response, coap_separate_t *separate_store, } } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-separate.h b/os/net/app-layer/coap/coap-separate.h index 1a89ed434b614f85cd9c07618da6b03c1644877d..97cbdbf92a357c5eed8e15e73d64b37e1623866d 100644 --- a/os/net/app-layer/coap/coap-separate.h +++ b/os/net/app-layer/coap/coap-separate.h @@ -36,15 +36,20 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_SEPARATE_H_ #define COAP_SEPARATE_H_ #include "coap.h" +#include "coap-engine.h" typedef struct coap_separate { - uip_ipaddr_t addr; - uint16_t port; + coap_endpoint_t endpoint; coap_message_type_t type; uint16_t mid; @@ -59,11 +64,14 @@ typedef struct coap_separate { uint16_t block2_size; } coap_separate_t; -int coap_separate_handler(resource_t *resource, void *request, - void *response); +int coap_separate_handler(coap_resource_t *resource, coap_message_t *request, + coap_message_t *response); void coap_separate_reject(void); -void coap_separate_accept(void *request, coap_separate_t *separate_store); -void coap_separate_resume(void *response, coap_separate_t *separate_store, +void coap_separate_accept(coap_message_t *request, + coap_separate_t *separate_store); +void coap_separate_resume(coap_message_t *response, + coap_separate_t *separate_store, uint8_t code); #endif /* COAP_SEPARATE_H_ */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-timer-default.c b/os/net/app-layer/coap/coap-timer-default.c new file mode 100644 index 0000000000000000000000000000000000000000..7da3dfb0592d455b7520f0e91fd5e709bc12f2e6 --- /dev/null +++ b/os/net/app-layer/coap/coap-timer-default.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * \file + * CoAP timer driver implementation based on Contiki etimers + * \author + * Niclas Finne <nfi@sics.se> + * Joakim Eriksson <joakime@sics.se> + */ + +/** + * \addtogroup coap-timer + * @{ + * + * \defgroup coap-timer-default CoAP timer for Contiki-NG + * @{ + * + * This is an implementation of CoAP timer for Contiki-NG. + */ + +#include "coap-timer.h" +#include "sys/clock.h" +#include "sys/etimer.h" +#include "sys/process.h" + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-timer" +#define LOG_LEVEL LOG_LEVEL_NONE + +PROCESS(coap_timer_process, "coap timer process"); + +static uint64_t current_time; +static struct etimer timer; +/*---------------------------------------------------------------------------*/ +static void +update_timer(void) +{ + uint64_t remaining; + remaining = coap_timer_time_to_next_expiration(); + LOG_DBG("remaining %lu msec\n", (unsigned long)remaining); + if(remaining == 0) { + /* Run as soon as possible */ + process_poll(&coap_timer_process); + } else { + remaining *= CLOCK_SECOND; + remaining /= 1000; + if(remaining > CLOCK_SECOND * 60) { + /* Make sure the CoAP timer clock is updated at least once per minute */ + remaining = CLOCK_SECOND * 60; + } else if(remaining < 1) { + /* Wait minimum one system clock tick */ + remaining = 1; + } + etimer_set(&timer, (clock_time_t)remaining); + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(coap_timer_process, ev, data) +{ + PROCESS_BEGIN(); + + etimer_set(&timer, CLOCK_SECOND); + while(1) { + PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER || + ev == PROCESS_EVENT_POLL); + + if(coap_timer_run()) { + /* Needs to run again */ + process_poll(&coap_timer_process); + } else { + update_timer(); + } + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +static uint64_t +uptime(void) +{ + static clock_time_t last; + clock_time_t now; + uint64_t diff; + + now = clock_time(); + diff = (clock_time_t)(now - last); + if(diff > 0) { + current_time += (diff * 1000) / CLOCK_SECOND; + last = now; + } + return current_time; +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ + process_start(&coap_timer_process, NULL); +} +/*---------------------------------------------------------------------------*/ +static void +update(void) +{ + process_poll(&coap_timer_process); +} +/*---------------------------------------------------------------------------*/ +const coap_timer_driver_t coap_timer_default_driver = { + .init = init, + .uptime = uptime, + .update = update, +}; +/*---------------------------------------------------------------------------*/ +/** @} */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-timer.c b/os/net/app-layer/coap/coap-timer.c new file mode 100644 index 0000000000000000000000000000000000000000..06a65c7f6c1853f3d5f09220222c6650e91bb5db --- /dev/null +++ b/os/net/app-layer/coap/coap-timer.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * \file + * CoAP timer implementation. + * \author + * Niclas Finne <nfi@sics.se> + * Joakim Eriksson <joakime@sics.se> + */ + +/** + * \addtogroup coap-timer + * @{ + */ + +#include "coap-timer.h" +#include "lib/list.h" +#include "sys/cc.h" + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-timer" +#define LOG_LEVEL LOG_LEVEL_NONE + +LIST(timer_list); +static uint8_t is_initialized; +/*---------------------------------------------------------------------------*/ +static void +add_timer(coap_timer_t *timer) +{ + coap_timer_t *n, *l, *p; + + if(!is_initialized) { + /* The coap_timer system has not yet been initialized */ + coap_timer_init(); + } + + LOG_DBG("adding timer %p at %lu\n", timer, + (unsigned long)timer->expiration_time); + + p = list_head(timer_list); + + /* Make sure the timer is not already added to the timer list */ + list_remove(timer_list, timer); + + for(l = NULL, n = list_head(timer_list); n != NULL; l = n, n = n->next) { + if(timer->expiration_time < n->expiration_time) { + list_insert(timer_list, l, timer); + timer = NULL; + break; + } + } + + if(timer != NULL) { + list_insert(timer_list, l, timer); + } + + if(p != list_head(timer_list)) { + /* The next timer to expire has changed so we need to notify the driver */ + COAP_TIMER_DRIVER.update(); + } +} +/*---------------------------------------------------------------------------*/ +void +coap_timer_stop(coap_timer_t *timer) +{ + LOG_DBG("stopping timer %p\n", timer); + + /* Mark timer as expired right now */ + timer->expiration_time = coap_timer_uptime(); + + list_remove(timer_list, timer); +} +/*---------------------------------------------------------------------------*/ +void +coap_timer_set(coap_timer_t *timer, uint64_t time) +{ + timer->expiration_time = coap_timer_uptime() + time; + add_timer(timer); +} +/*---------------------------------------------------------------------------*/ +void +coap_timer_reset(coap_timer_t *timer, uint64_t time) +{ + timer->expiration_time += time; + add_timer(timer); +} +/*---------------------------------------------------------------------------*/ +uint64_t +coap_timer_time_to_next_expiration(void) +{ + uint64_t now; + coap_timer_t *next; + + next = list_head(timer_list); + if(next == NULL) { + /* No pending timers - return a time in the future */ + return 60000; + } + + now = coap_timer_uptime(); + if(now < next->expiration_time) { + return next->expiration_time - now; + } + /* The next timer should already have expired */ + return 0; +} +/*---------------------------------------------------------------------------*/ +int +coap_timer_run(void) +{ + uint64_t now; + coap_timer_t *next; + + /* Always get the current time because it might trigger clock updates */ + now = coap_timer_uptime(); + + next = list_head(timer_list); + if(next == NULL) { + /* No pending timers */ + return 0; + } + + if(next->expiration_time <= now) { + LOG_DBG("timer %p expired at %lu\n", next, (unsigned long)now); + + /* This timer should expire now */ + list_remove(timer_list, next); + + if(next->callback) { + next->callback(next); + } + + /* The next timer has changed */ + COAP_TIMER_DRIVER.update(); + + /* Check if there is another pending timer */ + next = list_head(timer_list); + if(next != NULL && next->expiration_time <= coap_timer_uptime()) { + /* Need to run again */ + return 1; + } + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +void +coap_timer_init(void) +{ + if(is_initialized) { + return; + } + is_initialized = 1; + list_init(timer_list); + if(COAP_TIMER_DRIVER.init) { + COAP_TIMER_DRIVER.init(); + } +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-timer.h b/os/net/app-layer/coap/coap-timer.h new file mode 100644 index 0000000000000000000000000000000000000000..0461232ba4c206e160e4ac413a80c5f993d74589 --- /dev/null +++ b/os/net/app-layer/coap/coap-timer.h @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * \file + * CoAP timer API. + * \author + * Niclas Finne <nfi@sics.se> + * Joakim Eriksson <joakime@sics.se> + */ + +/** + * \addtogroup coap + * @{ + * + * \defgroup coap-timer CoAP timer API + * @{ + * + * The CoAP timer API defines a common interface for CoAP timer and time functionality. + */ + +#ifndef COAP_TIMER_H_ +#define COAP_TIMER_H_ + +#include "contiki.h" +#include <stdint.h> + +typedef struct coap_timer coap_timer_t; +struct coap_timer { + coap_timer_t *next; + void (* callback)(coap_timer_t *); + void *user_data; + uint64_t expiration_time; +}; + +typedef struct { + void (* init)(void); + uint64_t (* uptime)(void); + void (* update)(void); +} coap_timer_driver_t; + +#ifndef COAP_TIMER_DRIVER +#ifdef COAP_TIMER_CONF_DRIVER +#define COAP_TIMER_DRIVER COAP_TIMER_CONF_DRIVER +#else /* COAP_TIMER_CONF_DRIVER */ +#define COAP_TIMER_DRIVER coap_timer_default_driver +#endif /* COAP_TIMER_CONF_DRIVER */ +#endif /* COAP_TIMER_DRIVER */ + +extern const coap_timer_driver_t COAP_TIMER_DRIVER; + +/** + * \brief Get the time since boot in milliseconds. + * \return The number of milliseconds since boot. + */ +static inline uint64_t +coap_timer_uptime(void) +{ + return COAP_TIMER_DRIVER.uptime(); +} + +/** + * \brief Get the time since boot in seconds. + * \return The number of seconds since boot. + */ +static inline uint32_t +coap_timer_seconds(void) +{ + return (uint32_t)(COAP_TIMER_DRIVER.uptime() / 1000); +} + +/** + * \brief Set a callback function to be called when a CoAP timer expires. + * + * \param timer A pointer to a CoAP timer. + * \param callback A callback function. + */ +static inline void +coap_timer_set_callback(coap_timer_t *timer, void (* callback)(coap_timer_t *)) +{ + timer->callback = callback; +} + +/** + * \brief Get user data that has been attached to a CoAP timer. + * + * \param timer A pointer to a CoAP timer. + * \return An opaque pointer to user data or NULL if no user data is + * attached to the timer. + */ +static inline void * +coap_timer_get_user_data(coap_timer_t *timer) +{ + return timer->user_data; +} + +/** + * \brief Attach user data to a CoAP timer. + * + * \param timer A pointer to a CoAP timer. + * \param data An opaque pointer to user data. + */ +static inline void +coap_timer_set_user_data(coap_timer_t *timer, void *data) +{ + timer->user_data = data; +} + +/** + * \brief Check if a CoAP timer has expired. + * + * \param timer A pointer to a CoAP timer. + * \return Non-zero if the timer has expired, zero otherwise. + */ +static inline int +coap_timer_expired(const coap_timer_t *timer) +{ + return timer->expiration_time <= coap_timer_uptime(); +} + +/** + * \brief Stop a pending CoAP timer. + * + * After this function has been called, the timer will be expired + * and will not call the callback function. + * + * \param timer A pointer to a CoAP timer. + */ +void coap_timer_stop(coap_timer_t *timer); + +/** + * \brief Set a CoAP timer to expire after the specified time. + * + * \param timer A pointer to a CoAP timer. + * \param time The time until the timer expires. + */ +void coap_timer_set(coap_timer_t *timer, uint64_t time); + +/** + * \brief Reset a CoAP timer to expire a specified time after the + * last expiration time. + * + * This function sets the CoAP timer to expire the specified time + * after the previous expiration time. If the new expiration time + * has already passed, the timer will expire as soon as possible. + * + * If the timer has not yet expired when this function is called, + * the time until the timer expires will be extended by the + * specified time. + * + * \param timer A pointer to a CoAP timer. + * \param time The time after previous expiration the timer expires. + */ +void coap_timer_reset(coap_timer_t *timer, uint64_t time); + +/** + * Get the time until next CoAP timer expires or 0 if there already exists + * expired timers that have not yet been processed. This function is normally + * never called by application code. + * + * Returns the time to next CoAP timer expires or 0 if unprocessed expired + * timers exists. Returns a time in the future if there are no timers pending. + */ +uint64_t coap_timer_time_to_next_expiration(void); + +/** + * This function must be called periodically by the CoAP timer driver to + * process any expired CoAP timers. This function is normally never called by + * application code. + * + * Returns non-zero if it needs to run again to process more timers. + */ +int coap_timer_run(void); + +/** + * This function initializes the CoAP timer library. It is automatically + * called at first use of a CoAP timer. This function is normally never called + * by application code. + */ +void coap_timer_init(void); + +#endif /* COAP_TIMER_H_ */ +/** @} */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-transactions.c b/os/net/app-layer/coap/coap-transactions.c index 613557f4d5e3754f6cce06c01de9eb4750f74cd0..7e34d22e4fd624480b277d915a70bb0bcd90170e 100644 --- a/os/net/app-layer/coap/coap-transactions.c +++ b/os/net/app-layer/coap/coap-transactions.c @@ -36,39 +36,47 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ -#include "contiki.h" -#include "contiki-net.h" +/** + * \addtogroup coap + * @{ + */ + #include "coap-transactions.h" #include "coap-observe.h" +#include "coap-timer.h" +#include "lib/memb.h" +#include "lib/list.h" +#include <stdlib.h> -#define DEBUG 0 -#if DEBUG -#include <stdio.h> -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap" +#define LOG_LEVEL LOG_LEVEL_COAP /*---------------------------------------------------------------------------*/ MEMB(transactions_memb, coap_transaction_t, COAP_MAX_OPEN_TRANSACTIONS); LIST(transactions_list); -static struct process *transaction_handler_process = NULL; +/*---------------------------------------------------------------------------*/ +static void +coap_retransmit_transaction(coap_timer_t *nt) +{ + coap_transaction_t *t = coap_timer_get_user_data(nt); + if(t == NULL) { + LOG_DBG("No retransmission data in coap_timer!\n"); + return; + } + ++(t->retrans_counter); + LOG_DBG("Retransmitting %u (%u)\n", t->mid, t->retrans_counter); + coap_send_transaction(t); +} +/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*- Internal API ------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -void -coap_register_as_transaction_handler() -{ - transaction_handler_process = PROCESS_CURRENT(); -} coap_transaction_t * -coap_new_transaction(uint16_t mid, uip_ipaddr_t *addr, uint16_t port) +coap_new_transaction(uint16_t mid, const coap_endpoint_t *endpoint) { coap_transaction_t *t = memb_alloc(&transactions_memb); @@ -77,8 +85,7 @@ coap_new_transaction(uint16_t mid, uip_ipaddr_t *addr, uint16_t port) t->retrans_counter = 0; /* save client address */ - uip_ipaddr_copy(&t->addr, addr); - t->port = port; + coap_endpoint_copy(&t->endpoint, endpoint); list_add(transactions_list, t); /* list itself makes sure same element is not added twice */ } @@ -89,43 +96,40 @@ coap_new_transaction(uint16_t mid, uip_ipaddr_t *addr, uint16_t port) void coap_send_transaction(coap_transaction_t *t) { - PRINTF("Sending transaction %u\n", t->mid); + LOG_DBG("Sending transaction %u\n", t->mid); - coap_send_message(&t->addr, t->port, t->packet, t->packet_len); + coap_sendto(&t->endpoint, t->message, t->message_len); if(COAP_TYPE_CON == - ((COAP_HEADER_TYPE_MASK & t->packet[0]) >> COAP_HEADER_TYPE_POSITION)) { + ((COAP_HEADER_TYPE_MASK & t->message[0]) >> COAP_HEADER_TYPE_POSITION)) { if(t->retrans_counter < COAP_MAX_RETRANSMIT) { /* not timed out yet */ - PRINTF("Keeping transaction %u\n", t->mid); + LOG_DBG("Keeping transaction %u\n", t->mid); if(t->retrans_counter == 0) { - t->retrans_timer.timer.interval = - COAP_RESPONSE_TIMEOUT_TICKS + (random_rand() - % - (clock_time_t) + coap_timer_set_callback(&t->retrans_timer, coap_retransmit_transaction); + coap_timer_set_user_data(&t->retrans_timer, t); + t->retrans_interval = + COAP_RESPONSE_TIMEOUT_TICKS + (rand() % COAP_RESPONSE_TIMEOUT_BACKOFF_MASK); - PRINTF("Initial interval %f\n", - (float)t->retrans_timer.timer.interval / CLOCK_SECOND); + LOG_DBG("Initial interval %lu msec\n", + (unsigned long)t->retrans_interval); } else { - t->retrans_timer.timer.interval <<= 1; /* double */ - PRINTF("Doubled (%u) interval %f\n", t->retrans_counter, - (float)t->retrans_timer.timer.interval / CLOCK_SECOND); + t->retrans_interval <<= 1; /* double */ + LOG_DBG("Doubled (%u) interval %lu s\n", t->retrans_counter, + (unsigned long)(t->retrans_interval / 1000)); } - PROCESS_CONTEXT_BEGIN(transaction_handler_process); - etimer_restart(&t->retrans_timer); /* interval updated above */ - PROCESS_CONTEXT_END(transaction_handler_process); - - t = NULL; + /* interval updated above */ + coap_timer_set(&t->retrans_timer, t->retrans_interval); } else { /* timed out */ - PRINTF("Timeout\n"); - restful_response_handler callback = t->callback; + LOG_DBG("Timeout\n"); + coap_resource_response_handler_t callback = t->callback; void *callback_data = t->callback_data; /* handle observers */ - coap_remove_observer_by_client(&t->addr, t->port); + coap_remove_observer_by_client(&t->endpoint); coap_clear_transaction(t); @@ -142,13 +146,14 @@ void coap_clear_transaction(coap_transaction_t *t) { if(t) { - PRINTF("Freeing transaction %u: %p\n", t->mid, t); + LOG_DBG("Freeing transaction %u: %p\n", t->mid, t); - etimer_stop(&t->retrans_timer); + coap_timer_stop(&t->retrans_timer); list_remove(transactions_list, t); memb_free(&transactions_memb, t); } } +/*---------------------------------------------------------------------------*/ coap_transaction_t * coap_get_transaction_by_mid(uint16_t mid) { @@ -156,24 +161,11 @@ coap_get_transaction_by_mid(uint16_t mid) for(t = (coap_transaction_t *)list_head(transactions_list); t; t = t->next) { if(t->mid == mid) { - PRINTF("Found transaction for MID %u: %p\n", t->mid, t); + LOG_DBG("Found transaction for MID %u: %p\n", t->mid, t); return t; } } return NULL; } /*---------------------------------------------------------------------------*/ -void -coap_check_transactions() -{ - coap_transaction_t *t = NULL; - - for(t = (coap_transaction_t *)list_head(transactions_list); t; t = t->next) { - if(etimer_expired(&t->retrans_timer)) { - ++(t->retrans_counter); - PRINTF("Retransmitting %u (%u)\n", t->mid, t->retrans_counter); - coap_send_transaction(t); - } - } -} -/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap-transactions.h b/os/net/app-layer/coap/coap-transactions.h index 49e35c0f2435ddcad09151b0dd5e832bc94134cd..65334b4ebb60cb3b766146f6cb6b14d85d94935d 100644 --- a/os/net/app-layer/coap/coap-transactions.h +++ b/os/net/app-layer/coap/coap-transactions.h @@ -36,45 +36,48 @@ * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_TRANSACTIONS_H_ #define COAP_TRANSACTIONS_H_ #include "coap.h" +#include "coap-engine.h" +#include "coap-timer.h" /* * Modulo mask (thus +1) for a random number to get the tick number for the random * retransmission time between COAP_RESPONSE_TIMEOUT and COAP_RESPONSE_TIMEOUT*COAP_RESPONSE_RANDOM_FACTOR. */ -#define COAP_RESPONSE_TIMEOUT_TICKS (CLOCK_SECOND * COAP_RESPONSE_TIMEOUT) -#define COAP_RESPONSE_TIMEOUT_BACKOFF_MASK (long)((CLOCK_SECOND * COAP_RESPONSE_TIMEOUT * ((float)COAP_RESPONSE_RANDOM_FACTOR - 1.0)) + 0.5) + 1 +#define COAP_RESPONSE_TIMEOUT_TICKS (1000 * COAP_RESPONSE_TIMEOUT) +#define COAP_RESPONSE_TIMEOUT_BACKOFF_MASK (uint32_t)(((1000 * COAP_RESPONSE_TIMEOUT * ((float)COAP_RESPONSE_RANDOM_FACTOR - 1.0)) + 0.5) + 1) /* container for transactions with message buffer and retransmission info */ typedef struct coap_transaction { struct coap_transaction *next; /* for LIST */ uint16_t mid; - struct etimer retrans_timer; + coap_timer_t retrans_timer; + uint32_t retrans_interval; uint8_t retrans_counter; - uip_ipaddr_t addr; - uint16_t port; + coap_endpoint_t endpoint; - restful_response_handler callback; + coap_resource_response_handler_t callback; void *callback_data; - uint16_t packet_len; - uint8_t packet[COAP_MAX_PACKET_SIZE + 1]; /* +1 for the terminating '\0' which will not be sent + uint16_t message_len; + uint8_t message[COAP_MAX_PACKET_SIZE + 1]; /* +1 for the terminating '\0' which will not be sent * Use snprintf(buf, len+1, "", ...) to completely fill payload */ } coap_transaction_t; -void coap_register_as_transaction_handler(void); - -coap_transaction_t *coap_new_transaction(uint16_t mid, uip_ipaddr_t *addr, - uint16_t port); +coap_transaction_t *coap_new_transaction(uint16_t mid, const coap_endpoint_t *ep); void coap_send_transaction(coap_transaction_t *t); void coap_clear_transaction(coap_transaction_t *t); coap_transaction_t *coap_get_transaction_by_mid(uint16_t mid); -void coap_check_transactions(void); - #endif /* COAP_TRANSACTIONS_H_ */ +/** @} */ diff --git a/examples/coap/project-conf.h b/os/net/app-layer/coap/coap-transport.h similarity index 52% rename from examples/coap/project-conf.h rename to os/net/app-layer/coap/coap-transport.h index d8a3b1122617d934a14fd42019839737cd51324d..3de6f71dc567c8f09b2ee6f0e4b44187f5d96aaf 100644 --- a/examples/coap/project-conf.h +++ b/os/net/app-layer/coap/coap-transport.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * Copyright (c) 2016-2018, SICS, Swedish ICT AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,54 +25,60 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. */ /** * \file - * Erbium (Er) example project configuration. + * API for CoAP transport * \author - * Matthias Kovatsch <kovatsch@inf.ethz.ch> + * Niclas Finne <nfi@sics.se> + * Joakim Eriksson <joakime@sics.se> */ -#ifndef __PROJECT_ERBIUM_CONF_H__ -#define __PROJECT_ERBIUM_CONF_H__ - -/* Custom channel and PAN ID configuration for your project. */ -/* - #define RF_CHANNEL 26 - #define IEEE802154_CONF_PANID 0xABCD +/** + * \addtogroup coap + * @{ + * + * \defgroup coap-transport CoAP transport API + * @{ + * + * The CoAP transport API defines a common interface for sending/receiving + * CoAP messages. */ -/* IP buffer size must match all other hops, in particular the border router. */ -/* - #define UIP_CONF_BUFFER_SIZE 256 - */ +#ifndef COAP_TRANSPORT_H_ +#define COAP_TRANSPORT_H_ -/* Increase rpl-border-router IP-buffer when using more than 64. */ -#define REST_MAX_CHUNK_SIZE 48 +#include "coap-endpoint.h" -/* Estimate your header size, especially when using Proxy-Uri. */ -/* - #define COAP_MAX_HEADER_SIZE 70 +/** + * \brief Returns a common data buffer that can be used when + * generating CoAP messages for transmission. The buffer + * size is at least COAP_MAX_PACKET_SIZE bytes. + * + * In Contiki-NG, this corresponds to the uIP buffer. + * + * \return A pointer to a data buffer where a CoAP message can be stored. */ +uint8_t *coap_databuf(void); -/* Multiplies with chunk size, be aware of memory constraints. */ -#define COAP_MAX_OPEN_TRANSACTIONS 4 - -/* Must be <= open transactions, default is COAP_MAX_OPEN_TRANSACTIONS-1. */ -/* - #define COAP_MAX_OBSERVERS 2 +/** + * \brief Send a message to the specified CoAP endpoint + * \param ep A pointer to a CoAP endpoint + * \param data A pointer to data to send + * \param len The size of the data to send + * \return The number of bytes sent or negative if an error occurred. */ +int coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t len); -/* Filtering .well-known/core per query can be disabled to save space. */ -#define COAP_LINK_FORMAT_FILTERING 0 -#define COAP_PROXY_OPTION_PROCESSING 0 - -/* Turn off DAO-ACK to make code smaller */ -#define RPL_CONF_WITH_DAO_ACK 0 +/** + * \brief Initialize the CoAP transport. + * + * This function initializes the CoAP transport implementation and + * should only be called by the CoAP engine. + */ +void coap_transport_init(void); -/* Enable client-side support for COAP observe */ -#define COAP_OBSERVE_CLIENT 1 -#endif /* __PROJECT_ERBIUM_CONF_H__ */ +#endif /* COAP_TRANSPORT_H_ */ +/** @} */ +/** @} */ diff --git a/os/net/app-layer/coap/coap-uip.c b/os/net/app-layer/coap/coap-uip.c new file mode 100644 index 0000000000000000000000000000000000000000..8db2bbbbf2ec8bc72ac381eef890c58d06246671 --- /dev/null +++ b/os/net/app-layer/coap/coap-uip.c @@ -0,0 +1,613 @@ +/* + * Copyright (c) 2016, SICS, Swedish ICT AB. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * \file + * CoAP transport implementation for uIPv6 + * \author + * Niclas Finne <nfi@sics.se> + * Joakim Eriksson <joakime@sics.se> + */ + +/** + * \addtogroup coap-transport + * @{ + * + * \defgroup coap-uip CoAP transport implementation for uIP + * @{ + * + * This is an implementation of CoAP transport and CoAP endpoint over uIP + * with DTLS support. + */ + +#include "contiki.h" +#include "net/ipv6/uip-udp-packet.h" +#include "net/ipv6/uiplib.h" +#include "coap.h" +#include "coap-engine.h" +#include "coap-endpoint.h" +#include "coap-transport.h" +#include "coap-transactions.h" +#include "coap-constants.h" +#include "coap-keystore.h" +#include "coap-keystore-simple.h" + +#if UIP_CONF_IPV6_RPL +#include "rpl.h" +#endif /* UIP_CONF_IPV6_RPL */ + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-uip" +#define LOG_LEVEL LOG_LEVEL_COAP + +#ifdef WITH_DTLS +#include "tinydtls.h" +#include "dtls.h" +#endif /* WITH_DTLS */ + +/* sanity check for configured values */ +#if COAP_MAX_PACKET_SIZE > (UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPH_LEN - UIP_UDPH_LEN) +#error "UIP_CONF_BUFFER_SIZE too small for COAP_MAX_CHUNK_SIZE" +#endif + +#define SERVER_LISTEN_PORT UIP_HTONS(COAP_DEFAULT_PORT) +#define SERVER_LISTEN_SECURE_PORT UIP_HTONS(COAP_DEFAULT_SECURE_PORT) + +/* direct access into the buffer */ +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#if NETSTACK_CONF_WITH_IPV6 +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) +#else +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN]) +#endif + +#ifdef WITH_DTLS +static dtls_handler_t cb; +static dtls_context_t *dtls_context = NULL; + +static const coap_keystore_t *dtls_keystore = NULL; +static struct uip_udp_conn *dtls_conn = NULL; +#endif /* WITH_DTLS */ + +PROCESS(coap_engine, "CoAP Engine"); + +static struct uip_udp_conn *udp_conn = NULL; + +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_log(const coap_endpoint_t *ep) +{ + if(ep == NULL) { + LOG_OUTPUT("(NULL EP)"); + return; + } + if(ep->secure) { + LOG_OUTPUT("coaps://["); + } else { + LOG_OUTPUT("coap://["); + } + log_6addr(&ep->ipaddr); + LOG_OUTPUT("]:%u", uip_ntohs(ep->port)); +} +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_print(const coap_endpoint_t *ep) +{ + if(ep == NULL) { + printf("(NULL EP)"); + return; + } + if(ep->secure) { + printf("coaps://["); + } else { + printf("coap://["); + } + uiplib_ipaddr_print(&ep->ipaddr); + printf("]:%u", uip_ntohs(ep->port)); +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_snprint(char *buf, size_t size, const coap_endpoint_t *ep) +{ + int n; + if(buf == NULL || size == 0) { + return 0; + } + if(ep == NULL) { + n = snprintf(buf, size - 1, "(NULL EP)"); + } else { + if(ep->secure) { + n = snprintf(buf, size - 1, "coaps://["); + } else { + n = snprintf(buf, size - 1, "coap://["); + } + if(n < size - 1) { + n += uiplib_ipaddr_snprint(&buf[n], size - n - 1, &ep->ipaddr); + } + if(n < size - 1) { + n += snprintf(&buf[n], size -n - 1, "]:%u", uip_ntohs(ep->port)); + } + } + if(n >= size - 1) { + buf[size - 1] = '\0'; + } + return n; +} +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_copy(coap_endpoint_t *destination, + const coap_endpoint_t *from) +{ + uip_ipaddr_copy(&destination->ipaddr, &from->ipaddr); + destination->port = from->port; + destination->secure = from->secure; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2) +{ + if(!uip_ipaddr_cmp(&e1->ipaddr, &e2->ipaddr)) { + return 0; + } + return e1->port == e2->port && e1->secure == e2->secure; +} +/*---------------------------------------------------------------------------*/ +static int +index_of(const char *data, int offset, int len, uint8_t c) +{ + if(offset < 0) { + return offset; + } + for(; offset < len; offset++) { + if(data[offset] == c) { + return offset; + } + } + return -1; +} +/*---------------------------------------------------------------------------*/ +static int +get_port(const char *inbuf, size_t len, uint32_t *value) +{ + int i; + *value = 0; + for(i = 0; i < len; i++) { + if(inbuf[i] >= '0' && inbuf[i] <= '9') { + *value = *value * 10 + (inbuf[i] - '0'); + } else { + break; + } + } + return i; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep) +{ + /* Only IPv6 supported */ + int start = index_of(text, 0, size, '['); + int end = index_of(text, start, size, ']'); + int secure = strncmp((const char *)text, "coaps:", 6) == 0; + uint32_t port; + if(start > 0 && end > start && + uiplib_ipaddrconv((const char *)&text[start], &ep->ipaddr)) { + if(text[end + 1] == ':' && + get_port(text + end + 2, size - end - 2, &port)) { + ep->port = UIP_HTONS(port); + } else if(secure) { + /** + * Secure CoAP should use a different port but for now + * the same port is used. + */ + LOG_DBG("Using secure port (coaps)\n"); + ep->port = SERVER_LISTEN_SECURE_PORT; + ep->secure = 1; + } else { + ep->port = SERVER_LISTEN_PORT; + ep->secure = 0; + } + return 1; + } else { + if(uiplib_ipaddrconv((const char *)&text, &ep->ipaddr)) { + ep->port = SERVER_LISTEN_PORT; + ep->secure = 0; + return 1; + } + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static const coap_endpoint_t * +get_src_endpoint(uint8_t secure) +{ + static coap_endpoint_t src; + uip_ipaddr_copy(&src.ipaddr, &UIP_IP_BUF->srcipaddr); + src.port = UIP_UDP_BUF->srcport; + src.secure = secure; + return &src; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_is_secure(const coap_endpoint_t *ep) +{ + return ep->secure; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_is_connected(const coap_endpoint_t *ep) +{ +#if UIP_CONF_IPV6_RPL +#ifndef CONTIKI_TARGET_NATIVE + if(rpl_get_any_dag() == NULL) { + return 0; + } +#endif +#endif /* UIP_CONF_IPV6_RPL */ + +#ifdef WITH_DTLS + if(ep != NULL && ep->secure != 0) { + dtls_peer_t *peer; + if(dtls_context == NULL) { + return 0; + } + peer = dtls_get_peer(dtls_context, ep); + if(peer != NULL) { + /* only if handshake is done! */ + LOG_DBG("DTLS peer state for "); + LOG_DBG_COAP_EP(ep); + LOG_DBG_(" is %d (%sconnected)\n", peer->state, + dtls_peer_is_connected(peer) ? "" : "not "); + return dtls_peer_is_connected(peer); + } else { + LOG_DBG("DTLS did not find peer "); + LOG_DBG_COAP_EP(ep); + LOG_DBG_("\n"); + return 0; + } + } +#endif /* WITH_DTLS */ + + /* Assume connected */ + return 1; +} +/*---------------------------------------------------------------------------*/ +int +coap_endpoint_connect(coap_endpoint_t *ep) +{ + if(ep->secure == 0) { + LOG_DBG("connect to "); + LOG_DBG_COAP_EP(ep); + LOG_DBG_("\n"); + return 1; + } + +#ifdef WITH_DTLS + LOG_DBG("DTLS connect to "); + LOG_DBG_COAP_EP(ep); + LOG_DBG_("\n"); + + /* setup all address info here... should be done to connect */ + if(dtls_context) { + dtls_connect(dtls_context, ep); + return 1; + } +#endif /* WITH_DTLS */ + + return 0; +} +/*---------------------------------------------------------------------------*/ +void +coap_endpoint_disconnect(coap_endpoint_t *ep) +{ +#ifdef WITH_DTLS + if(ep && ep->secure && dtls_context) { + dtls_close(dtls_context, ep); + } +#endif /* WITH_DTLS */ +} +/*---------------------------------------------------------------------------*/ +uint8_t * +coap_databuf(void) +{ + return uip_appdata; +} +/*---------------------------------------------------------------------------*/ +void +coap_transport_init(void) +{ + process_start(&coap_engine, NULL); +#ifdef WITH_DTLS + dtls_init(); + +#if COAP_DTLS_KEYSTORE_CONF_WITH_SIMPLE + coap_keystore_simple_init(); +#endif /* COAP_DTLS_KEYSTORE_CONF_WITH_SIMPLE */ + +#endif /* WITH_DTLS */ +} +/*---------------------------------------------------------------------------*/ +#ifdef WITH_DTLS +static void +process_secure_data(void) +{ + LOG_INFO("receiving secure UDP datagram from ["); + LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr); + LOG_INFO_("]:%u\n", uip_ntohs(UIP_UDP_BUF->srcport)); + LOG_INFO(" Length: %u\n", uip_datalen()); + + if(dtls_context) { + dtls_handle_message(dtls_context, (coap_endpoint_t *)get_src_endpoint(1), + uip_appdata, uip_datalen()); + } +} +#endif /* WITH_DTLS */ +/*---------------------------------------------------------------------------*/ +static void +process_data(void) +{ + LOG_INFO("receiving UDP datagram from ["); + LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr); + LOG_INFO_("]:%u\n", uip_ntohs(UIP_UDP_BUF->srcport)); + LOG_INFO(" Length: %u\n", uip_datalen()); + + coap_receive(get_src_endpoint(0), uip_appdata, uip_datalen()); +} +/*---------------------------------------------------------------------------*/ +int +coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t length) +{ + if(ep == NULL) { + LOG_WARN("failed to send - no endpoint\n"); + return -1; + } + + if(!coap_endpoint_is_connected(ep)) { + LOG_WARN("endpoint "); + LOG_WARN_COAP_EP(ep); + LOG_WARN_(" not connected - dropping packet\n"); + return -1; + } + +#ifdef WITH_DTLS + if(coap_endpoint_is_secure(ep)) { + if(dtls_context) { + int ret; + + ret = dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, length); + LOG_INFO("sent DTLS to "); + LOG_INFO_COAP_EP(ep); + if(ret < 0) { + LOG_INFO_(" - error %d\n", ret); + } else { + LOG_INFO_(" %d/%u bytes\n", ret, length); + } + return ret; + } else { + LOG_WARN("no DTLS context\n"); + return -1; + } + } +#endif /* WITH_DTLS */ + + uip_udp_packet_sendto(udp_conn, data, length, &ep->ipaddr, ep->port); + LOG_INFO("sent to "); + LOG_INFO_COAP_EP(ep); + LOG_INFO_(" %u bytes\n", length); + return length; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(coap_engine, ev, data) +{ + PROCESS_BEGIN(); + + /* new connection with remote host */ + udp_conn = udp_new(NULL, 0, NULL); + udp_bind(udp_conn, SERVER_LISTEN_PORT); + LOG_INFO("Listening on port %u\n", uip_ntohs(udp_conn->lport)); + +#ifdef WITH_DTLS + /* create new context with app-data */ + dtls_conn = udp_new(NULL, 0, NULL); + if(dtls_conn != NULL) { + udp_bind(dtls_conn, SERVER_LISTEN_SECURE_PORT); + LOG_INFO("DTLS listening on port %u\n", uip_ntohs(dtls_conn->lport)); + dtls_context = dtls_new_context(dtls_conn); + } + if(!dtls_context) { + LOG_WARN("DTLS: cannot create context\n"); + } else { + dtls_set_handler(dtls_context, &cb); + } +#endif /* WITH_DTLS */ + + while(1) { + PROCESS_YIELD(); + + if(ev == tcpip_event) { + if(uip_newdata()) { +#ifdef WITH_DTLS + if(uip_udp_conn == dtls_conn) { + process_secure_data(); + continue; + } +#endif /* WITH_DTLS */ + process_data(); + } + } + } /* while (1) */ + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ + +/* DTLS */ +#ifdef WITH_DTLS + +/* This is input coming from the DTLS code - e.g. de-crypted input from + the other side - peer */ +static int +input_from_peer(struct dtls_context_t *ctx, + session_t *session, uint8_t *data, size_t len) +{ + size_t i; + + if(LOG_DBG_ENABLED) { + LOG_DBG("received DTLS data:"); + for(i = 0; i < len; i++) { + LOG_DBG_("%c", data[i]); + } + LOG_DBG_("\n"); + LOG_DBG("Hex:"); + for(i = 0; i < len; i++) { + LOG_DBG_("%02x", data[i]); + } + LOG_DBG_("\n"); + } + + /* Ensure that the endpoint is tagged as secure */ + session->secure = 1; + + coap_receive(session, data, len); + + return 0; +} + +/* This is output from the DTLS code to be sent to peer (encrypted) */ +static int +output_to_peer(struct dtls_context_t *ctx, + session_t *session, uint8_t *data, size_t len) +{ + struct uip_udp_conn *udp_connection = dtls_get_app_data(ctx); + LOG_DBG("output_to DTLS peer ["); + LOG_DBG_6ADDR(&session->ipaddr); + LOG_DBG_("]:%u %ld bytes\n", uip_ntohs(session->port), (long)len); + uip_udp_packet_sendto(udp_connection, data, len, + &session->ipaddr, session->port); + return len; +} + +/* This defines the key-store set API since we hookup DTLS here */ +void +coap_set_keystore(const coap_keystore_t *keystore) +{ + dtls_keystore = keystore; +} + +/* This function is the "key store" for tinyDTLS. It is called to + * retrieve a key for the given identity within this particular + * session. */ +static int +get_psk_info(struct dtls_context_t *ctx, + const session_t *session, + dtls_credentials_type_t type, + const unsigned char *id, size_t id_len, + unsigned char *result, size_t result_length) +{ + coap_keystore_psk_entry_t ks; + + if(dtls_keystore == NULL) { + LOG_DBG("--- No key store available ---\n"); + return 0; + } + + memset(&ks, 0, sizeof(ks)); + LOG_DBG("---===>>> Getting the Key or ID <<<===---\n"); + switch(type) { + case DTLS_PSK_IDENTITY: + if(id && id_len) { + ks.identity_hint = id; + ks.identity_hint_len = id_len; + LOG_DBG("got psk_identity_hint: '"); + LOG_DBG_COAP_STRING((const char *)id, id_len); + LOG_DBG_("'\n"); + } + + if(dtls_keystore->coap_get_psk_info) { + /* we know that session is a coap endpoint */ + dtls_keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks); + } + if(ks.identity == NULL || ks.identity_len == 0) { + LOG_DBG("no psk_identity found\n"); + return 0; + } + + if(result_length < ks.identity_len) { + LOG_DBG("cannot return psk_identity -- buffer too small\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + memcpy(result, ks.identity, ks.identity_len); + LOG_DBG("psk_identity with %u bytes found\n", ks.identity_len); + return ks.identity_len; + + case DTLS_PSK_KEY: + if(dtls_keystore->coap_get_psk_info) { + ks.identity = id; + ks.identity_len = id_len; + /* we know that session is a coap endpoint */ + dtls_keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks); + } + if(ks.key == NULL || ks.key_len == 0) { + LOG_DBG("PSK for unknown id requested, exiting\n"); + return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER); + } + + if(result_length < ks.key_len) { + LOG_DBG("cannot return psk -- buffer too small\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } + memcpy(result, ks.key, ks.key_len); + LOG_DBG("psk with %u bytes found\n", ks.key_len); + return ks.key_len; + + default: + LOG_WARN("unsupported key store request type: %d\n", type); + } + + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); +} + + +static dtls_handler_t cb = { + .write = output_to_peer, + .read = input_from_peer, + .event = NULL, +#ifdef DTLS_PSK + .get_psk_info = get_psk_info, +#endif /* DTLS_PSK */ +#ifdef DTLS_ECC + /* .get_ecdsa_key = get_ecdsa_key, */ + /* .verify_ecdsa_key = verify_ecdsa_key */ +#endif /* DTLS_ECC */ +}; + +#endif /* WITH_DTLS */ +/*---------------------------------------------------------------------------*/ +/** @} */ +/** @} */ diff --git a/os/net/app-layer/coap/coap.c b/os/net/app-layer/coap/coap.c index da466e6d7c502e37931c453e225f5670a5e465d4..c28e2d8b509a540694985a346f18c11ae369aba0 100644 --- a/os/net/app-layer/coap/coap.c +++ b/os/net/app-layer/coap/coap.c @@ -34,37 +34,36 @@ * An implementation of the Constrained Application Protocol (RFC). * \author * Matthias Kovatsch <kovatsch@inf.ethz.ch> + * + * Joakim Eriksson, joakim.eriksson@ri.se + * Niclas Finne, niclas.finne@ri.se + */ + +/** + * \addtogroup coap + * @{ */ + #include <string.h> -#include <stdio.h> -#include "contiki.h" +#include <stdlib.h> #include "sys/cc.h" -#include "contiki-net.h" #include "coap.h" #include "coap-transactions.h" -#define DEBUG 0 -#if DEBUG -#include <stdio.h> -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap" +#define LOG_LEVEL LOG_LEVEL_COAP /*---------------------------------------------------------------------------*/ /*- Variables ---------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -static struct uip_udp_conn *udp_conn = NULL; static uint16_t current_mid = 0; -coap_status_t erbium_status_code = NO_ERROR; -char *coap_error_message = ""; +coap_status_t coap_status_code = NO_ERROR; +const char *coap_error_message = ""; /*---------------------------------------------------------------------------*/ /*- Local helper functions --------------------------------------------------*/ /*---------------------------------------------------------------------------*/ @@ -127,7 +126,7 @@ coap_set_option_header(unsigned int delta, size_t length, uint8_t *buffer) buffer[++written] = (length - 13); } - PRINTF("WRITTEN %zu B opt header\n", 1 + written); + LOG_DBG("WRITTEN %zu B opt header\n", 1 + written); return ++written; } @@ -150,8 +149,8 @@ coap_serialize_int_option(unsigned int number, unsigned int current_number, if(0xFFFFFFFF & value) { ++i; } - PRINTF("OPTION %u (delta %u, len %zu)\n", number, number - current_number, - i); + LOG_DBG("OPTION %u (delta %u, len %zu)\n", number, number - current_number, + i); i = coap_set_option_header(number - current_number, i, buffer); @@ -177,8 +176,9 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number, { size_t i = 0; - PRINTF("ARRAY type %u, len %zu, full [%.*s]\n", number, length, - (int)length, array); + LOG_DBG("ARRAY type %u, len %zu, full [", number, length); + LOG_DBG_COAP_STRING((const char *)array, length); + LOG_DBG_("]\n"); if(split_char != '\0') { int j; @@ -187,7 +187,7 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number, size_t temp_length; for(j = 0; j <= length + 1; ++j) { - PRINTF("STEP %u/%zu (%c)\n", j, length, array[j]); + LOG_DBG("STEP %u/%zu (%c)\n", j, length, array[j]); if(array[j] == split_char || j == length) { part_end = array + j; temp_length = part_end - part_start; @@ -197,9 +197,10 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number, memcpy(&buffer[i], part_start, temp_length); i += temp_length; - PRINTF("OPTION type %u, delta %u, len %zu, part [%.*s]\n", number, - number - current_number, i, (int)temp_length, part_start); - + LOG_DBG("OPTION type %u, delta %u, len %zu, part [", number, + number - current_number, i); + LOG_DBG_COAP_STRING((const char *)part_start, temp_length); + LOG_DBG_("]\n"); ++j; /* skip the splitter */ current_number = number; part_start = array + j; @@ -210,8 +211,8 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number, memcpy(&buffer[i], array, length); i += length; - PRINTF("OPTION type %u, delta %u, len %zu\n", number, - number - current_number, length); + LOG_DBG("OPTION type %u, delta %u, len %zu\n", number, + number - current_number, length); } return i; @@ -276,15 +277,10 @@ coap_get_variable(const char *buffer, size_t length, const char *name, /*- Internal API ------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ void -coap_init_connection(uint16_t port) +coap_init_connection(void) { - /* new connection with remote host */ - udp_conn = udp_new(NULL, 0, NULL); - udp_bind(udp_conn, port); - PRINTF("Listening on port %u\n", uip_ntohs(udp_conn->lport)); - /* initialize transaction ID */ - current_mid = random_rand(); + current_mid = rand(); } /*---------------------------------------------------------------------------*/ uint16_t @@ -294,13 +290,11 @@ coap_get_mid() } /*---------------------------------------------------------------------------*/ void -coap_init_message(void *packet, coap_message_type_t type, uint8_t code, - uint16_t mid) +coap_init_message(coap_message_t *coap_pkt, coap_message_type_t type, + uint8_t code, uint16_t mid) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - /* Important thing */ - memset(coap_pkt, 0, sizeof(coap_packet_t)); + memset(coap_pkt, 0, sizeof(coap_message_t)); coap_pkt->type = type; coap_pkt->code = code; @@ -308,9 +302,8 @@ coap_init_message(void *packet, coap_message_type_t type, uint8_t code, } /*---------------------------------------------------------------------------*/ size_t -coap_serialize_message(void *packet, uint8_t *buffer) +coap_serialize_message(coap_message_t *coap_pkt, uint8_t *buffer) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; uint8_t *option; unsigned int current_number = 0; @@ -318,7 +311,7 @@ coap_serialize_message(void *packet, uint8_t *buffer) coap_pkt->buffer = buffer; coap_pkt->version = 1; - PRINTF("-Serializing MID %u to %p, ", coap_pkt->mid, coap_pkt->buffer); + LOG_DBG("-Serializing MID %u to %p, ", coap_pkt->mid, coap_pkt->buffer); /* set header fields */ coap_pkt->buffer[0] = 0x00; @@ -332,27 +325,27 @@ coap_serialize_message(void *packet, uint8_t *buffer) coap_pkt->buffer[2] = (uint8_t)((coap_pkt->mid) >> 8); coap_pkt->buffer[3] = (uint8_t)(coap_pkt->mid); - /* empty packet, dont need to do more stuff */ + /* empty message, dont need to do more stuff */ if(!coap_pkt->code) { - PRINTF("-Done serializing empty message at %p-\n", coap_pkt->buffer); + LOG_DBG_("-Done serializing empty message at %p-\n", coap_pkt->buffer); return 4; } /* set Token */ - PRINTF("Token (len %u)", coap_pkt->token_len); + LOG_DBG_("Token (len %u)", coap_pkt->token_len); option = coap_pkt->buffer + COAP_HEADER_LEN; for(current_number = 0; current_number < coap_pkt->token_len; ++current_number) { - PRINTF(" %02X", coap_pkt->token[current_number]); + LOG_DBG_(" %02X", coap_pkt->token[current_number]); *option = coap_pkt->token[current_number]; ++option; } - PRINTF("-\n"); + LOG_DBG_("-\n"); /* Serialize options */ current_number = 0; - PRINTF("-Serializing options at %p-\n", option); + LOG_DBG("-Serializing options at %p-\n", option); /* The options must be serialized in the order of their number */ COAP_SERIALIZE_BYTE_OPTION(COAP_OPTION_IF_MATCH, if_match, "If-Match"); @@ -370,7 +363,7 @@ coap_serialize_message(void *packet, uint8_t *buffer) "Location-Path"); COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_PATH, uri_path, '/', "Uri-Path"); - PRINTF("Serialize content format: %d\n", coap_pkt->content_format); + LOG_DBG("Serialize content format: %d\n", coap_pkt->content_format); COAP_SERIALIZE_INT_OPTION(COAP_OPTION_CONTENT_FORMAT, content_format, "Content-Format"); COAP_SERIALIZE_INT_OPTION(COAP_OPTION_MAX_AGE, max_age, "Max-Age"); @@ -388,7 +381,7 @@ coap_serialize_message(void *packet, uint8_t *buffer) "Proxy-Scheme"); COAP_SERIALIZE_INT_OPTION(COAP_OPTION_SIZE1, size1, "Size1"); - PRINTF("-Done serializing at %p----\n", option); + LOG_DBG("-Done serializing at %p----\n", option); /* Pack payload */ if((option - coap_pkt->buffer) <= COAP_MAX_HEADER_SIZE) { @@ -405,49 +398,26 @@ coap_serialize_message(void *packet, uint8_t *buffer) return 0; } - PRINTF("-Done %u B (header len %u, payload len %u)-\n", - (unsigned int)(coap_pkt->payload_len + option - buffer), - (unsigned int)(option - buffer), - (unsigned int)coap_pkt->payload_len); - - PRINTF("Dump [0x%02X %02X %02X %02X %02X %02X %02X %02X]\n", - coap_pkt->buffer[0], - coap_pkt->buffer[1], - coap_pkt->buffer[2], - coap_pkt->buffer[3], - coap_pkt->buffer[4], - coap_pkt->buffer[5], coap_pkt->buffer[6], coap_pkt->buffer[7] - ); - - return (option - buffer) + coap_pkt->payload_len; /* packet length */ -} -/*---------------------------------------------------------------------------*/ -void -coap_send_message(uip_ipaddr_t *addr, uint16_t port, uint8_t *data, - uint16_t length) -{ - /* configure connection to reply to client */ - uip_ipaddr_copy(&udp_conn->ripaddr, addr); - udp_conn->rport = port; - - uip_udp_packet_send(udp_conn, data, length); + LOG_DBG("-Done %u B (header len %u, payload len %u)-\n", + (unsigned int)(coap_pkt->payload_len + option - buffer), + (unsigned int)(option - buffer), + (unsigned int)coap_pkt->payload_len); - PRINTF("-sent UDP datagram (%u)-\n", length); + LOG_DBG("Dump [0x%02X %02X %02X %02X %02X %02X %02X %02X]\n", + coap_pkt->buffer[0], coap_pkt->buffer[1], coap_pkt->buffer[2], + coap_pkt->buffer[3], coap_pkt->buffer[4], coap_pkt->buffer[5], + coap_pkt->buffer[6], coap_pkt->buffer[7]); - /* restore server socket to allow data from any node */ - memset(&udp_conn->ripaddr, 0, sizeof(udp_conn->ripaddr)); - udp_conn->rport = 0; + return (option - buffer) + coap_pkt->payload_len; /* message length */ } /*---------------------------------------------------------------------------*/ coap_status_t -coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) +coap_parse_message(coap_message_t *coap_pkt, uint8_t *data, uint16_t data_len) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; + /* initialize message */ + memset(coap_pkt, 0, sizeof(coap_message_t)); - /* initialize packet */ - memset(coap_pkt, 0, sizeof(coap_packet_t)); - - /* pointer to packet bytes */ + /* pointer to message bytes */ coap_pkt->buffer = data; /* parse header fields */ @@ -473,11 +443,11 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) uint8_t *current_option = data + COAP_HEADER_LEN; memcpy(coap_pkt->token, current_option, coap_pkt->token_len); - PRINTF("Token (len %u) [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", - coap_pkt->token_len, coap_pkt->token[0], coap_pkt->token[1], - coap_pkt->token[2], coap_pkt->token[3], coap_pkt->token[4], - coap_pkt->token[5], coap_pkt->token[6], coap_pkt->token[7] - ); /*FIXME always prints 8 bytes */ + LOG_DBG("Token (len %u) [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", + coap_pkt->token_len, coap_pkt->token[0], coap_pkt->token[1], + coap_pkt->token[2], coap_pkt->token[3], coap_pkt->token[4], + coap_pkt->token[5], coap_pkt->token[6], coap_pkt->token[7] + ); /* FIXME always prints 8 bytes */ /* parse options */ memset(coap_pkt->options, 0, sizeof(coap_pkt->options)); @@ -493,9 +463,9 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) coap_pkt->payload = ++current_option; coap_pkt->payload_len = data_len - (coap_pkt->payload - data); - /* also for receiving, the Erbium upper bound is REST_MAX_CHUNK_SIZE */ - if(coap_pkt->payload_len > REST_MAX_CHUNK_SIZE) { - coap_pkt->payload_len = REST_MAX_CHUNK_SIZE; + /* also for receiving, the Erbium upper bound is COAP_MAX_CHUNK_SIZE */ + if(coap_pkt->payload_len > COAP_MAX_CHUNK_SIZE) { + coap_pkt->payload_len = COAP_MAX_CHUNK_SIZE; /* null-terminate payload */ } coap_pkt->payload[coap_pkt->payload_len] = '\0'; @@ -531,74 +501,74 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) if(current_option + option_length > data + data_len) { /* Malformed CoAP - out of bounds */ - PRINTF("BAD REQUEST: options outside data packet: %u > %u\n", - (unsigned)(current_option + option_length - data), data_len); + LOG_WARN("BAD REQUEST: options outside data message: %u > %u\n", + (unsigned)(current_option + option_length - data), data_len); return BAD_REQUEST_4_00; } - option_number += option_delta; + option_number += option_delta; if(option_number > COAP_OPTION_SIZE1) { /* Malformed CoAP - out of bounds */ - PRINTF("BAD REQUEST: option number too large: %u\n", option_number); + LOG_WARN("BAD REQUEST: option number too large: %u\n", option_number); return BAD_REQUEST_4_00; } - option_number += option_delta; - - PRINTF("OPTION %u (delta %u, len %zu): ", option_number, option_delta, - option_length); + LOG_DBG("OPTION %u (delta %u, len %zu): ", option_number, option_delta, + option_length); - SET_OPTION(coap_pkt, option_number); + coap_set_option(coap_pkt, option_number); switch(option_number) { case COAP_OPTION_CONTENT_FORMAT: coap_pkt->content_format = coap_parse_int_option(current_option, option_length); - PRINTF("Content-Format [%u]\n", coap_pkt->content_format); + LOG_DBG_("Content-Format [%u]\n", coap_pkt->content_format); break; case COAP_OPTION_MAX_AGE: coap_pkt->max_age = coap_parse_int_option(current_option, option_length); - PRINTF("Max-Age [%lu]\n", (unsigned long)coap_pkt->max_age); + LOG_DBG_("Max-Age [%"PRIu32"]\n", coap_pkt->max_age); break; case COAP_OPTION_ETAG: coap_pkt->etag_len = MIN(COAP_ETAG_LEN, option_length); memcpy(coap_pkt->etag, current_option, coap_pkt->etag_len); - PRINTF("ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", - coap_pkt->etag_len, coap_pkt->etag[0], coap_pkt->etag[1], - coap_pkt->etag[2], coap_pkt->etag[3], coap_pkt->etag[4], - coap_pkt->etag[5], coap_pkt->etag[6], coap_pkt->etag[7] - ); /*FIXME always prints 8 bytes */ + LOG_DBG_("ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", + coap_pkt->etag_len, coap_pkt->etag[0], coap_pkt->etag[1], + coap_pkt->etag[2], coap_pkt->etag[3], coap_pkt->etag[4], + coap_pkt->etag[5], coap_pkt->etag[6], coap_pkt->etag[7] + ); /*FIXME always prints 8 bytes */ break; case COAP_OPTION_ACCEPT: coap_pkt->accept = coap_parse_int_option(current_option, option_length); - PRINTF("Accept [%u]\n", coap_pkt->accept); + LOG_DBG_("Accept [%u]\n", coap_pkt->accept); break; case COAP_OPTION_IF_MATCH: /* TODO support multiple ETags */ coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, option_length); memcpy(coap_pkt->if_match, current_option, coap_pkt->if_match_len); - PRINTF("If-Match %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", - coap_pkt->if_match_len, coap_pkt->if_match[0], - coap_pkt->if_match[1], coap_pkt->if_match[2], - coap_pkt->if_match[3], coap_pkt->if_match[4], - coap_pkt->if_match[5], coap_pkt->if_match[6], - coap_pkt->if_match[7] - ); /* FIXME always prints 8 bytes */ + LOG_DBG_("If-Match %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", + coap_pkt->if_match_len, coap_pkt->if_match[0], + coap_pkt->if_match[1], coap_pkt->if_match[2], + coap_pkt->if_match[3], coap_pkt->if_match[4], + coap_pkt->if_match[5], coap_pkt->if_match[6], + coap_pkt->if_match[7] + ); /* FIXME always prints 8 bytes */ break; case COAP_OPTION_IF_NONE_MATCH: coap_pkt->if_none_match = 1; - PRINTF("If-None-Match\n"); + LOG_DBG_("If-None-Match\n"); break; case COAP_OPTION_PROXY_URI: #if COAP_PROXY_OPTION_PROCESSING coap_pkt->proxy_uri = (char *)current_option; coap_pkt->proxy_uri_len = option_length; -#endif - PRINTF("Proxy-Uri NOT IMPLEMENTED [%.*s]\n", (int)coap_pkt->proxy_uri_len, - coap_pkt->proxy_uri); +#endif /* COAP_PROXY_OPTION_PROCESSING */ + LOG_DBG_("Proxy-Uri NOT IMPLEMENTED ["); + LOG_DBG_COAP_STRING(coap_pkt->proxy_uri, coap_pkt->proxy_uri_len); + LOG_DBG_("]\n"); + coap_error_message = "This is a constrained server (Contiki)"; return PROXYING_NOT_SUPPORTED_5_05; break; @@ -607,8 +577,9 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) coap_pkt->proxy_scheme = (char *)current_option; coap_pkt->proxy_scheme_len = option_length; #endif - PRINTF("Proxy-Scheme NOT IMPLEMENTED [%.*s]\n", - (int)coap_pkt->proxy_scheme_len, coap_pkt->proxy_scheme); + LOG_DBG_("Proxy-Scheme NOT IMPLEMENTED ["); + LOG_DBG_COAP_STRING(coap_pkt->proxy_scheme, coap_pkt->proxy_scheme_len); + LOG_DBG_("]\n"); coap_error_message = "This is a constrained server (Contiki)"; return PROXYING_NOT_SUPPORTED_5_05; break; @@ -616,51 +587,58 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) case COAP_OPTION_URI_HOST: coap_pkt->uri_host = (char *)current_option; coap_pkt->uri_host_len = option_length; - PRINTF("Uri-Host [%.*s]\n", (int)coap_pkt->uri_host_len, - coap_pkt->uri_host); + LOG_DBG_("Uri-Host ["); + LOG_DBG_COAP_STRING(coap_pkt->uri_host, coap_pkt->uri_host_len); + LOG_DBG_("]\n"); break; case COAP_OPTION_URI_PORT: coap_pkt->uri_port = coap_parse_int_option(current_option, option_length); - PRINTF("Uri-Port [%u]\n", coap_pkt->uri_port); + LOG_DBG_("Uri-Port [%u]\n", coap_pkt->uri_port); break; case COAP_OPTION_URI_PATH: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ + /* coap_merge_multi_option() operates in-place on the IPBUF, but final message field should be const string -> cast to string */ coap_merge_multi_option((char **)&(coap_pkt->uri_path), &(coap_pkt->uri_path_len), current_option, option_length, '/'); - PRINTF("Uri-Path [%.*s]\n", (int)coap_pkt->uri_path_len, coap_pkt->uri_path); + LOG_DBG_("Uri-Path ["); + LOG_DBG_COAP_STRING(coap_pkt->uri_path, coap_pkt->uri_path_len); + LOG_DBG_("]\n"); break; case COAP_OPTION_URI_QUERY: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ + /* coap_merge_multi_option() operates in-place on the IPBUF, but final message field should be const string -> cast to string */ coap_merge_multi_option((char **)&(coap_pkt->uri_query), &(coap_pkt->uri_query_len), current_option, option_length, '&'); - PRINTF("Uri-Query [%.*s]\n", (int)coap_pkt->uri_query_len, - coap_pkt->uri_query); + LOG_DBG_("Uri-Query["); + LOG_DBG_COAP_STRING(coap_pkt->uri_query, coap_pkt->uri_query_len); + LOG_DBG_("]\n"); break; case COAP_OPTION_LOCATION_PATH: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ + /* coap_merge_multi_option() operates in-place on the IPBUF, but final message field should be const string -> cast to string */ coap_merge_multi_option((char **)&(coap_pkt->location_path), &(coap_pkt->location_path_len), current_option, option_length, '/'); - PRINTF("Location-Path [%.*s]\n", (int)coap_pkt->location_path_len, - coap_pkt->location_path); + + LOG_DBG_("Location-Path ["); + LOG_DBG_COAP_STRING(coap_pkt->location_path, coap_pkt->location_path_len); + LOG_DBG_("]\n"); break; case COAP_OPTION_LOCATION_QUERY: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ + /* coap_merge_multi_option() operates in-place on the IPBUF, but final message field should be const string -> cast to string */ coap_merge_multi_option((char **)&(coap_pkt->location_query), &(coap_pkt->location_query_len), current_option, option_length, '&'); - PRINTF("Location-Query [%.*s]\n", (int)coap_pkt->location_query_len, - coap_pkt->location_query); + LOG_DBG_("Location-Query ["); + LOG_DBG_COAP_STRING(coap_pkt->location_query, coap_pkt->location_query_len); + LOG_DBG_("]\n"); break; case COAP_OPTION_OBSERVE: coap_pkt->observe = coap_parse_int_option(current_option, option_length); - PRINTF("Observe [%lu]\n", (unsigned long)coap_pkt->observe); + LOG_DBG_("Observe [%"PRId32"]\n", coap_pkt->observe); break; case COAP_OPTION_BLOCK2: coap_pkt->block2_num = coap_parse_int_option(current_option, @@ -670,9 +648,9 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) coap_pkt->block2_offset = (coap_pkt->block2_num & ~0x0000000F) << (coap_pkt->block2_num & 0x07); coap_pkt->block2_num >>= 4; - PRINTF("Block2 [%lu%s (%u B/blk)]\n", - (unsigned long)coap_pkt->block2_num, - coap_pkt->block2_more ? "+" : "", coap_pkt->block2_size); + LOG_DBG_("Block2 [%lu%s (%u B/blk)]\n", + (unsigned long)coap_pkt->block2_num, + coap_pkt->block2_more ? "+" : "", coap_pkt->block2_size); break; case COAP_OPTION_BLOCK1: coap_pkt->block1_num = coap_parse_int_option(current_option, @@ -682,20 +660,20 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) coap_pkt->block1_offset = (coap_pkt->block1_num & ~0x0000000F) << (coap_pkt->block1_num & 0x07); coap_pkt->block1_num >>= 4; - PRINTF("Block1 [%lu%s (%u B/blk)]\n", - (unsigned long)coap_pkt->block1_num, - coap_pkt->block1_more ? "+" : "", coap_pkt->block1_size); + LOG_DBG_("Block1 [%lu%s (%u B/blk)]\n", + (unsigned long)coap_pkt->block1_num, + coap_pkt->block1_more ? "+" : "", coap_pkt->block1_size); break; case COAP_OPTION_SIZE2: coap_pkt->size2 = coap_parse_int_option(current_option, option_length); - PRINTF("Size2 [%lu]\n", (unsigned long)coap_pkt->size2); + LOG_DBG_("Size2 [%"PRIu32"]\n", coap_pkt->size2); break; case COAP_OPTION_SIZE1: coap_pkt->size1 = coap_parse_int_option(current_option, option_length); - PRINTF("Size1 [%lu]\n", (unsigned long)coap_pkt->size1); + LOG_DBG_("Size1 [%"PRIu32"]\n", coap_pkt->size1); break; default: - PRINTF("unknown (%u)\n", option_number); + LOG_DBG_("unknown (%u)\n", option_number); /* check if critical (odd) */ if(option_number & 1) { coap_error_message = "Unsupported critical option"; @@ -705,29 +683,27 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) current_option += option_length; } /* for */ - PRINTF("-Done parsing-------\n"); + LOG_DBG("-Done parsing-------\n"); return NO_ERROR; } /*---------------------------------------------------------------------------*/ -/*- REST Engine API ---------------------------------------------------------*/ +/*- CoAP Engine API ---------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ int -coap_get_query_variable(void *packet, const char *name, const char **output) +coap_get_query_variable(coap_message_t *coap_pkt, + const char *name, const char **output) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(IS_OPTION(coap_pkt, COAP_OPTION_URI_QUERY)) { + if(coap_is_option(coap_pkt, COAP_OPTION_URI_QUERY)) { return coap_get_variable(coap_pkt->uri_query, coap_pkt->uri_query_len, name, output); } return 0; } int -coap_get_post_variable(void *packet, const char *name, const char **output) +coap_get_post_variable(coap_message_t *coap_pkt, + const char *name, const char **output) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - if(coap_pkt->payload_len) { return coap_get_variable((const char *)coap_pkt->payload, coap_pkt->payload_len, name, output); @@ -736,10 +712,10 @@ coap_get_post_variable(void *packet, const char *name, const char **output) } /*---------------------------------------------------------------------------*/ int -coap_set_status_code(void *packet, unsigned int code) +coap_set_status_code(coap_message_t *message, unsigned int code) { if(code <= 0xFF) { - ((coap_packet_t *)packet)->code = (uint8_t)code; + message->code = (uint8_t)code; return 1; } else { return 0; @@ -747,329 +723,280 @@ coap_set_status_code(void *packet, unsigned int code) } /*---------------------------------------------------------------------------*/ int -coap_set_token(void *packet, const uint8_t *token, size_t token_len) +coap_set_token(coap_message_t *coap_pkt, const uint8_t *token, size_t token_len) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->token_len = MIN(COAP_TOKEN_LEN, token_len); memcpy(coap_pkt->token, token, coap_pkt->token_len); return coap_pkt->token_len; } /*---------------------------------------------------------------------------*/ -/*- CoAP REST Implementation API --------------------------------------------*/ +/*- CoAP Implementation API -------------------------------------------------*/ /*---------------------------------------------------------------------------*/ int -coap_get_header_content_format(void *packet, unsigned int *format) +coap_get_header_content_format(coap_message_t *coap_pkt, unsigned int *format) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_CONTENT_FORMAT)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_CONTENT_FORMAT)) { return 0; } *format = coap_pkt->content_format; return 1; } int -coap_set_header_content_format(void *packet, unsigned int format) +coap_set_header_content_format(coap_message_t *coap_pkt, unsigned int format) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->content_format = format; - SET_OPTION(coap_pkt, COAP_OPTION_CONTENT_FORMAT); + coap_set_option(coap_pkt, COAP_OPTION_CONTENT_FORMAT); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_accept(void *packet, unsigned int *accept) +coap_get_header_accept(coap_message_t *coap_pkt, unsigned int *accept) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_ACCEPT)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_ACCEPT)) { return 0; } *accept = coap_pkt->accept; return 1; } int -coap_set_header_accept(void *packet, unsigned int accept) +coap_set_header_accept(coap_message_t *coap_pkt, unsigned int accept) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->accept = accept; - SET_OPTION(coap_pkt, COAP_OPTION_ACCEPT); + coap_set_option(coap_pkt, COAP_OPTION_ACCEPT); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_max_age(void *packet, uint32_t *age) +coap_get_header_max_age(coap_message_t *coap_pkt, uint32_t *age) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_MAX_AGE)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_MAX_AGE)) { *age = COAP_DEFAULT_MAX_AGE; } else { *age = coap_pkt->max_age; } return 1; } int -coap_set_header_max_age(void *packet, uint32_t age) +coap_set_header_max_age(coap_message_t *coap_pkt, uint32_t age) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->max_age = age; - SET_OPTION(coap_pkt, COAP_OPTION_MAX_AGE); + coap_set_option(coap_pkt, COAP_OPTION_MAX_AGE); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_etag(void *packet, const uint8_t **etag) +coap_get_header_etag(coap_message_t *coap_pkt, const uint8_t **etag) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_ETAG)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_ETAG)) { return 0; } *etag = coap_pkt->etag; return coap_pkt->etag_len; } int -coap_set_header_etag(void *packet, const uint8_t *etag, size_t etag_len) +coap_set_header_etag(coap_message_t *coap_pkt, const uint8_t *etag, size_t etag_len) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->etag_len = MIN(COAP_ETAG_LEN, etag_len); memcpy(coap_pkt->etag, etag, coap_pkt->etag_len); - SET_OPTION(coap_pkt, COAP_OPTION_ETAG); + coap_set_option(coap_pkt, COAP_OPTION_ETAG); return coap_pkt->etag_len; } /*---------------------------------------------------------------------------*/ /*FIXME support multiple ETags */ int -coap_get_header_if_match(void *packet, const uint8_t **etag) +coap_get_header_if_match(coap_message_t *coap_pkt, const uint8_t **etag) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_IF_MATCH)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_IF_MATCH)) { return 0; } *etag = coap_pkt->if_match; return coap_pkt->if_match_len; } int -coap_set_header_if_match(void *packet, const uint8_t *etag, size_t etag_len) +coap_set_header_if_match(coap_message_t *coap_pkt, const uint8_t *etag, size_t etag_len) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, etag_len); memcpy(coap_pkt->if_match, etag, coap_pkt->if_match_len); - SET_OPTION(coap_pkt, COAP_OPTION_IF_MATCH); + coap_set_option(coap_pkt, COAP_OPTION_IF_MATCH); return coap_pkt->if_match_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_if_none_match(void *packet) +coap_get_header_if_none_match(coap_message_t *message) { - return IS_OPTION((coap_packet_t *)packet, - COAP_OPTION_IF_NONE_MATCH) ? 1 : 0; + return coap_is_option(message, COAP_OPTION_IF_NONE_MATCH) ? 1 : 0; } int -coap_set_header_if_none_match(void *packet) +coap_set_header_if_none_match(coap_message_t *message) { - SET_OPTION((coap_packet_t *)packet, COAP_OPTION_IF_NONE_MATCH); + coap_set_option(message, COAP_OPTION_IF_NONE_MATCH); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_proxy_uri(void *packet, const char **uri) +coap_get_header_proxy_uri(coap_message_t *coap_pkt, const char **uri) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_PROXY_URI)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_PROXY_URI)) { return 0; } *uri = coap_pkt->proxy_uri; return coap_pkt->proxy_uri_len; } int -coap_set_header_proxy_uri(void *packet, const char *uri) +coap_set_header_proxy_uri(coap_message_t *coap_pkt, const char *uri) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - /*TODO Provide alternative that sets Proxy-Scheme and Uri-* options and provide coap-conf define */ + /* TODO Provide alternative that sets Proxy-Scheme and Uri-* options and provide coap-conf define */ coap_pkt->proxy_uri = uri; coap_pkt->proxy_uri_len = strlen(uri); - SET_OPTION(coap_pkt, COAP_OPTION_PROXY_URI); + coap_set_option(coap_pkt, COAP_OPTION_PROXY_URI); return coap_pkt->proxy_uri_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_uri_host(void *packet, const char **host) +coap_get_header_uri_host(coap_message_t *coap_pkt, const char **host) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_URI_HOST)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_URI_HOST)) { return 0; } *host = coap_pkt->uri_host; return coap_pkt->uri_host_len; } int -coap_set_header_uri_host(void *packet, const char *host) +coap_set_header_uri_host(coap_message_t *coap_pkt, const char *host) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->uri_host = host; coap_pkt->uri_host_len = strlen(host); - SET_OPTION(coap_pkt, COAP_OPTION_URI_HOST); + coap_set_option(coap_pkt, COAP_OPTION_URI_HOST); return coap_pkt->uri_host_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_uri_path(void *packet, const char **path) +coap_get_header_uri_path(coap_message_t *coap_pkt, const char **path) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_URI_PATH)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_URI_PATH)) { return 0; } *path = coap_pkt->uri_path; return coap_pkt->uri_path_len; } int -coap_set_header_uri_path(void *packet, const char *path) +coap_set_header_uri_path(coap_message_t *coap_pkt, const char *path) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - while(path[0] == '/') + while(path[0] == '/') { ++path; + } coap_pkt->uri_path = path; coap_pkt->uri_path_len = strlen(path); - SET_OPTION(coap_pkt, COAP_OPTION_URI_PATH); + coap_set_option(coap_pkt, COAP_OPTION_URI_PATH); return coap_pkt->uri_path_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_uri_query(void *packet, const char **query) +coap_get_header_uri_query(coap_message_t *coap_pkt, const char **query) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_URI_QUERY)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_URI_QUERY)) { return 0; } *query = coap_pkt->uri_query; return coap_pkt->uri_query_len; } int -coap_set_header_uri_query(void *packet, const char *query) +coap_set_header_uri_query(coap_message_t *coap_pkt, const char *query) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - while(query[0] == '?') + while(query[0] == '?') { ++query; + } coap_pkt->uri_query = query; coap_pkt->uri_query_len = strlen(query); - SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY); + coap_set_option(coap_pkt, COAP_OPTION_URI_QUERY); return coap_pkt->uri_query_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_location_path(void *packet, const char **path) +coap_get_header_location_path(coap_message_t *coap_pkt, const char **path) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_PATH)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_LOCATION_PATH)) { return 0; } *path = coap_pkt->location_path; return coap_pkt->location_path_len; } int -coap_set_header_location_path(void *packet, const char *path) +coap_set_header_location_path(coap_message_t *coap_pkt, const char *path) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - char *query; - while(path[0] == '/') + while(path[0] == '/') { ++path; + } if((query = strchr(path, '?'))) { - coap_set_header_location_query(packet, query + 1); + coap_set_header_location_query(coap_pkt, query + 1); coap_pkt->location_path_len = query - path; } else { coap_pkt->location_path_len = strlen(path); } coap_pkt->location_path = path; if(coap_pkt->location_path_len > 0) { - SET_OPTION(coap_pkt, COAP_OPTION_LOCATION_PATH); + coap_set_option(coap_pkt, COAP_OPTION_LOCATION_PATH); } return coap_pkt->location_path_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_location_query(void *packet, const char **query) +coap_get_header_location_query(coap_message_t *coap_pkt, const char **query) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_LOCATION_QUERY)) { return 0; } *query = coap_pkt->location_query; return coap_pkt->location_query_len; } int -coap_set_header_location_query(void *packet, const char *query) +coap_set_header_location_query(coap_message_t *coap_pkt, const char *query) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - while(query[0] == '?') + while(query[0] == '?') { ++query; + } coap_pkt->location_query = query; coap_pkt->location_query_len = strlen(query); - SET_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY); + coap_set_option(coap_pkt, COAP_OPTION_LOCATION_QUERY); return coap_pkt->location_query_len; } /*---------------------------------------------------------------------------*/ int -coap_get_header_observe(void *packet, uint32_t *observe) +coap_get_header_observe(coap_message_t *coap_pkt, uint32_t *observe) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_OBSERVE)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_OBSERVE)) { return 0; } *observe = coap_pkt->observe; return 1; } int -coap_set_header_observe(void *packet, uint32_t observe) +coap_set_header_observe(coap_message_t *coap_pkt, uint32_t observe) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->observe = observe; - SET_OPTION(coap_pkt, COAP_OPTION_OBSERVE); + coap_set_option(coap_pkt, COAP_OPTION_OBSERVE); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_block2(void *packet, uint32_t *num, uint8_t *more, +coap_get_header_block2(coap_message_t *coap_pkt, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK2)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_BLOCK2)) { return 0; } /* pointers may be NULL to get only specific block parameters */ @@ -1088,11 +1015,9 @@ coap_get_header_block2(void *packet, uint32_t *num, uint8_t *more, return 1; } int -coap_set_header_block2(void *packet, uint32_t num, uint8_t more, +coap_set_header_block2(coap_message_t *coap_pkt, uint32_t num, uint8_t more, uint16_t size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - if(size < 16) { return 0; } @@ -1106,17 +1031,15 @@ coap_set_header_block2(void *packet, uint32_t num, uint8_t more, coap_pkt->block2_more = more ? 1 : 0; coap_pkt->block2_size = size; - SET_OPTION(coap_pkt, COAP_OPTION_BLOCK2); + coap_set_option(coap_pkt, COAP_OPTION_BLOCK2); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_block1(void *packet, uint32_t *num, uint8_t *more, +coap_get_header_block1(coap_message_t *coap_pkt, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK1)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_BLOCK1)) { return 0; } /* pointers may be NULL to get only specific block parameters */ @@ -1135,11 +1058,9 @@ coap_get_header_block1(void *packet, uint32_t *num, uint8_t *more, return 1; } int -coap_set_header_block1(void *packet, uint32_t num, uint8_t more, +coap_set_header_block1(coap_message_t *coap_pkt, uint32_t num, uint8_t more, uint16_t size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - if(size < 16) { return 0; } @@ -1153,73 +1074,59 @@ coap_set_header_block1(void *packet, uint32_t num, uint8_t more, coap_pkt->block1_more = more; coap_pkt->block1_size = size; - SET_OPTION(coap_pkt, COAP_OPTION_BLOCK1); + coap_set_option(coap_pkt, COAP_OPTION_BLOCK1); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_size2(void *packet, uint32_t *size) +coap_get_header_size2(coap_message_t *coap_pkt, uint32_t *size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_SIZE2)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_SIZE2)) { return 0; } *size = coap_pkt->size2; return 1; } int -coap_set_header_size2(void *packet, uint32_t size) +coap_set_header_size2(coap_message_t *coap_pkt, uint32_t size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->size2 = size; - SET_OPTION(coap_pkt, COAP_OPTION_SIZE2); + coap_set_option(coap_pkt, COAP_OPTION_SIZE2); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_header_size1(void *packet, uint32_t *size) +coap_get_header_size1(coap_message_t *coap_pkt, uint32_t *size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(!IS_OPTION(coap_pkt, COAP_OPTION_SIZE1)) { + if(!coap_is_option(coap_pkt, COAP_OPTION_SIZE1)) { return 0; } *size = coap_pkt->size1; return 1; } int -coap_set_header_size1(void *packet, uint32_t size) +coap_set_header_size1(coap_message_t *coap_pkt, uint32_t size) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->size1 = size; - SET_OPTION(coap_pkt, COAP_OPTION_SIZE1); + coap_set_option(coap_pkt, COAP_OPTION_SIZE1); return 1; } /*---------------------------------------------------------------------------*/ int -coap_get_payload(void *packet, const uint8_t **payload) +coap_get_payload(coap_message_t *coap_pkt, const uint8_t **payload) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(coap_pkt->payload) { + if(payload != NULL) { *payload = coap_pkt->payload; - return coap_pkt->payload_len; - } else { - *payload = NULL; - return 0; } + return coap_pkt->payload != NULL ? coap_pkt->payload_len : 0; } int -coap_set_payload(void *packet, const void *payload, size_t length) +coap_set_payload(coap_message_t *coap_pkt, const void *payload, size_t length) { - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - coap_pkt->payload = (uint8_t *)payload; - coap_pkt->payload_len = MIN(REST_MAX_CHUNK_SIZE, length); + coap_pkt->payload_len = MIN(COAP_MAX_CHUNK_SIZE, length); return coap_pkt->payload_len; } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/net/app-layer/coap/coap.h b/os/net/app-layer/coap/coap.h index 9d88886afc009559a54b7f2bcbebe3beed75fbac..8d9aed61c481d01297486dac5d0d1bb3f958c028 100644 --- a/os/net/app-layer/coap/coap.h +++ b/os/net/app-layer/coap/coap.h @@ -31,53 +31,51 @@ /** * \file - * An implementation of the Constrained Application Protocol (RFC). + * An implementation of the Constrained Application Protocol (RFC 7252). * \author * Matthias Kovatsch <kovatsch@inf.ethz.ch> */ -#ifndef ER_COAP_H_ -#define ER_COAP_H_ +/** + * \addtogroup apps + * @{ + * + * \defgroup coap An implementation of CoAP + * @{ + * + * This is an implementation of the Constrained Application Protocol + */ + +#ifndef COAP_H_ +#define COAP_H_ #include <stddef.h> /* for size_t */ -#include "contiki-net.h" #include "coap-constants.h" #include "coap-conf.h" +#include "coap-transport.h" -/* sanity check for configured values */ -#define COAP_MAX_PACKET_SIZE (COAP_MAX_HEADER_SIZE + REST_MAX_CHUNK_SIZE) -#if COAP_MAX_PACKET_SIZE > (UIP_BUFSIZE - UIP_IPH_LEN - UIP_UDPH_LEN) -#error "UIP_CONF_BUFFER_SIZE too small for REST_MAX_CHUNK_SIZE" -#endif - -/* use Erbium CoAP for the REST Engine. Must come before include of rest-engine.h. */ -#define REST coap_rest_implementation -#include "rest-engine.h" +/** + * \brief The max size of the CoAP messages + */ +#define COAP_MAX_PACKET_SIZE (COAP_MAX_HEADER_SIZE + COAP_MAX_CHUNK_SIZE) -/* REST_MAX_CHUNK_SIZE can be different from 2^x so we need to get next lower 2^x for COAP_MAX_BLOCK_SIZE */ +/* COAP_MAX_CHUNK_SIZE can be different from 2^x so we need to get next lower 2^x for COAP_MAX_BLOCK_SIZE */ #ifndef COAP_MAX_BLOCK_SIZE -#define COAP_MAX_BLOCK_SIZE (REST_MAX_CHUNK_SIZE < 32 ? 16 : \ - (REST_MAX_CHUNK_SIZE < 64 ? 32 : \ - (REST_MAX_CHUNK_SIZE < 128 ? 64 : \ - (REST_MAX_CHUNK_SIZE < 256 ? 128 : \ - (REST_MAX_CHUNK_SIZE < 512 ? 256 : \ - (REST_MAX_CHUNK_SIZE < 1024 ? 512 : \ - (REST_MAX_CHUNK_SIZE < 2048 ? 1024 : 2048))))))) +#define COAP_MAX_BLOCK_SIZE (COAP_MAX_CHUNK_SIZE < 32 ? 16 : \ + (COAP_MAX_CHUNK_SIZE < 64 ? 32 : \ + (COAP_MAX_CHUNK_SIZE < 128 ? 64 : \ + (COAP_MAX_CHUNK_SIZE < 256 ? 128 : \ + (COAP_MAX_CHUNK_SIZE < 512 ? 256 : \ + (COAP_MAX_CHUNK_SIZE < 1024 ? 512 : \ + (COAP_MAX_CHUNK_SIZE < 2048 ? 1024 : 2048))))))) #endif /* COAP_MAX_BLOCK_SIZE */ -/* direct access into the buffer */ -#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) -#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) - /* bitmap for set options */ -enum { OPTION_MAP_SIZE = sizeof(uint8_t) * 8 }; - -#define SET_OPTION(packet, opt) ((packet)->options[opt / OPTION_MAP_SIZE] |= 1 << (opt % OPTION_MAP_SIZE)) -#define IS_OPTION(packet, opt) ((packet)->options[opt / OPTION_MAP_SIZE] & (1 << (opt % OPTION_MAP_SIZE))) +#define COAP_OPTION_MAP_SIZE (sizeof(uint8_t) * 8) /* parsed message struct */ typedef struct { - uint8_t *buffer; /* pointer to CoAP header / incoming packet buffer / memory to serialize packet */ + uint8_t *buffer; /* pointer to CoAP header / incoming message buffer / memory to serialize message */ uint8_t version; coap_message_type_t type; @@ -87,7 +85,7 @@ typedef struct { uint8_t token_len; uint8_t token[COAP_TOKEN_LEN]; - uint8_t options[COAP_OPTION_SIZE1 / OPTION_MAP_SIZE + 1]; /* bitmap to check if option is set */ + uint8_t options[COAP_OPTION_SIZE1 / COAP_OPTION_MAP_SIZE + 1]; /* bitmap to check if option is set */ uint16_t content_format; /* parse options once and store; allows setting options in random order */ uint32_t max_age; @@ -124,20 +122,39 @@ typedef struct { const char *uri_query; uint8_t if_none_match; + const coap_endpoint_t *src_ep; + uint16_t payload_len; uint8_t *payload; -} coap_packet_t; +} coap_message_t; + +static inline int +coap_set_option(coap_message_t *message, unsigned int opt) +{ + if(opt > COAP_OPTION_SIZE1) { + return 0; + } + message->options[opt / COAP_OPTION_MAP_SIZE] |= 1 << (opt % COAP_OPTION_MAP_SIZE); + return 1; +} + +static inline int +coap_is_option(const coap_message_t *message, unsigned int opt) +{ + return (opt <= COAP_OPTION_SIZE1) && + (message->options[opt / COAP_OPTION_MAP_SIZE] & (1 << (opt % COAP_OPTION_MAP_SIZE))) != 0; +} /* option format serialization */ #define COAP_SERIALIZE_INT_OPTION(number, field, text) \ - if(IS_OPTION(coap_pkt, number)) { \ - PRINTF(text " [%u]\n", (unsigned int)coap_pkt->field); \ + if(coap_is_option(coap_pkt, number)) { \ + LOG_DBG(text " [%u]\n", (unsigned int)coap_pkt->field); \ option += coap_serialize_int_option(number, current_number, option, coap_pkt->field); \ current_number = number; \ } #define COAP_SERIALIZE_BYTE_OPTION(number, field, text) \ - if(IS_OPTION(coap_pkt, number)) { \ - PRINTF(text " %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", (unsigned int)coap_pkt->field##_len, \ + if(coap_is_option(coap_pkt, number)) { \ + LOG_DBG(text " %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", (unsigned int)coap_pkt->field##_len, \ coap_pkt->field[0], \ coap_pkt->field[1], \ coap_pkt->field[2], \ @@ -150,110 +167,138 @@ typedef struct { option += coap_serialize_array_option(number, current_number, option, coap_pkt->field, coap_pkt->field##_len, '\0'); \ current_number = number; \ } -#define COAP_SERIALIZE_STRING_OPTION(number, field, splitter, text) \ - if(IS_OPTION(coap_pkt, number)) { \ - PRINTF(text " [%.*s]\n", (int)coap_pkt->field##_len, coap_pkt->field); \ +#define COAP_SERIALIZE_STRING_OPTION(number, field, splitter, text) \ + if(coap_is_option(coap_pkt, number)) { \ + LOG_DBG(text " ["); \ + LOG_DBG_COAP_STRING(coap_pkt->field, coap_pkt->field##_len); \ + LOG_DBG_("]\n"); \ option += coap_serialize_array_option(number, current_number, option, (uint8_t *)coap_pkt->field, coap_pkt->field##_len, splitter); \ current_number = number; \ } #define COAP_SERIALIZE_BLOCK_OPTION(number, field, text) \ - if(IS_OPTION(coap_pkt, number)) \ - { \ - PRINTF(text " [%lu%s (%u B/blk)]\n", (unsigned long)coap_pkt->field##_num, coap_pkt->field##_more ? "+" : "", coap_pkt->field##_size); \ + if(coap_is_option(coap_pkt, number)) { \ + LOG_DBG(text " [%lu%s (%u B/blk)]\n", (unsigned long)coap_pkt->field##_num, coap_pkt->field##_more ? "+" : "", coap_pkt->field##_size); \ uint32_t block = coap_pkt->field##_num << 4; \ if(coap_pkt->field##_more) { block |= 0x8; } \ block |= 0xF & coap_log_2(coap_pkt->field##_size / 16); \ - PRINTF(text " encoded: 0x%lX\n", (unsigned long)block); \ + LOG_DBG(text " encoded: 0x%lX\n", (unsigned long)block); \ option += coap_serialize_int_option(number, current_number, option, block); \ current_number = number; \ } /* to store error code and human-readable payload */ -extern coap_status_t erbium_status_code; -extern char *coap_error_message; +extern coap_status_t coap_status_code; +extern const char *coap_error_message; -void coap_init_connection(uint16_t port); +void coap_init_connection(void); uint16_t coap_get_mid(void); -void coap_init_message(void *packet, coap_message_type_t type, uint8_t code, - uint16_t mid); -size_t coap_serialize_message(void *packet, uint8_t *buffer); -void coap_send_message(uip_ipaddr_t *addr, uint16_t port, uint8_t *data, - uint16_t length); -coap_status_t coap_parse_message(void *request, uint8_t *data, +void coap_init_message(coap_message_t *message, coap_message_type_t type, + uint8_t code, uint16_t mid); +size_t coap_serialize_message(coap_message_t *message, uint8_t *buffer); +coap_status_t coap_parse_message(coap_message_t *request, uint8_t *data, uint16_t data_len); -int coap_get_query_variable(void *packet, const char *name, +int coap_get_query_variable(coap_message_t *message, const char *name, const char **output); -int coap_get_post_variable(void *packet, const char *name, +int coap_get_post_variable(coap_message_t *message, const char *name, const char **output); +static inline coap_resource_flags_t +coap_get_method_type(coap_message_t *message) +{ + return (coap_resource_flags_t)(1 << (message->code - 1)); +} + +static inline const coap_endpoint_t * +coap_get_src_endpoint(coap_message_t *request) +{ + return request->src_ep; +} + +static inline void +coap_set_src_endpoint(coap_message_t *request, const coap_endpoint_t *ep) +{ + request->src_ep = ep; +} /*---------------------------------------------------------------------------*/ -int coap_set_status_code(void *packet, unsigned int code); +int coap_set_status_code(coap_message_t *message, unsigned int code); -int coap_set_token(void *packet, const uint8_t *token, size_t token_len); +int coap_set_token(coap_message_t *message, const uint8_t *token, + size_t token_len); -int coap_get_header_content_format(void *packet, unsigned int *format); -int coap_set_header_content_format(void *packet, unsigned int format); +int coap_get_header_content_format(coap_message_t *message, unsigned int *format); +int coap_set_header_content_format(coap_message_t *message, unsigned int format); -int coap_get_header_accept(void *packet, unsigned int *accept); -int coap_set_header_accept(void *packet, unsigned int accept); +int coap_get_header_accept(coap_message_t *message, unsigned int *accept); +int coap_set_header_accept(coap_message_t *message, unsigned int accept); -int coap_get_header_max_age(void *packet, uint32_t *age); -int coap_set_header_max_age(void *packet, uint32_t age); +int coap_get_header_max_age(coap_message_t *message, uint32_t *age); +int coap_set_header_max_age(coap_message_t *message, uint32_t age); -int coap_get_header_etag(void *packet, const uint8_t **etag); -int coap_set_header_etag(void *packet, const uint8_t *etag, size_t etag_len); +int coap_get_header_etag(coap_message_t *message, const uint8_t **etag); +int coap_set_header_etag(coap_message_t *message, const uint8_t *etag, + size_t etag_len); -int coap_get_header_if_match(void *packet, const uint8_t **etag); -int coap_set_header_if_match(void *packet, const uint8_t *etag, +int coap_get_header_if_match(coap_message_t *message, const uint8_t **etag); +int coap_set_header_if_match(coap_message_t *message, const uint8_t *etag, size_t etag_len); -int coap_get_header_if_none_match(void *packet); -int coap_set_header_if_none_match(void *packet); +int coap_get_header_if_none_match(coap_message_t *message); +int coap_set_header_if_none_match(coap_message_t *message); -int coap_get_header_proxy_uri(void *packet, const char **uri); /* in-place string might not be 0-terminated. */ -int coap_set_header_proxy_uri(void *packet, const char *uri); +/* in-place string might not be 0-terminated. */ +int coap_get_header_proxy_uri(coap_message_t *message, const char **uri); +int coap_set_header_proxy_uri(coap_message_t *message, const char *uri); -int coap_get_header_proxy_scheme(void *packet, const char **scheme); /* in-place string might not be 0-terminated. */ -int coap_set_header_proxy_scheme(void *packet, const char *scheme); +/* in-place string might not be 0-terminated. */ +int coap_get_header_proxy_scheme(coap_message_t *message, const char **scheme); +int coap_set_header_proxy_scheme(coap_message_t *message, const char *scheme); -int coap_get_header_uri_host(void *packet, const char **host); /* in-place string might not be 0-terminated. */ -int coap_set_header_uri_host(void *packet, const char *host); +/* in-place string might not be 0-terminated. */ +int coap_get_header_uri_host(coap_message_t *message, const char **host); +int coap_set_header_uri_host(coap_message_t *message, const char *host); -int coap_get_header_uri_path(void *packet, const char **path); /* in-place string might not be 0-terminated. */ -int coap_set_header_uri_path(void *packet, const char *path); +/* in-place string might not be 0-terminated. */ +int coap_get_header_uri_path(coap_message_t *message, const char **path); +int coap_set_header_uri_path(coap_message_t *message, const char *path); -int coap_get_header_uri_query(void *packet, const char **query); /* in-place string might not be 0-terminated. */ -int coap_set_header_uri_query(void *packet, const char *query); +/* in-place string might not be 0-terminated. */ +int coap_get_header_uri_query(coap_message_t *message, const char **query); +int coap_set_header_uri_query(coap_message_t *message, const char *query); -int coap_get_header_location_path(void *packet, const char **path); /* in-place string might not be 0-terminated. */ -int coap_set_header_location_path(void *packet, const char *path); /* also splits optional query into Location-Query option. */ +/* in-place string might not be 0-terminated. */ +int coap_get_header_location_path(coap_message_t *message, const char **path); +/* also splits optional query into Location-Query option. */ +int coap_set_header_location_path(coap_message_t *message, const char *path); -int coap_get_header_location_query(void *packet, const char **query); /* in-place string might not be 0-terminated. */ -int coap_set_header_location_query(void *packet, const char *query); +/* in-place string might not be 0-terminated. */ +int coap_get_header_location_query(coap_message_t *message, const char **query); +int coap_set_header_location_query(coap_message_t *message, const char *query); -int coap_get_header_observe(void *packet, uint32_t *observe); -int coap_set_header_observe(void *packet, uint32_t observe); +int coap_get_header_observe(coap_message_t *message, uint32_t *observe); +int coap_set_header_observe(coap_message_t *message, uint32_t observe); -int coap_get_header_block2(void *packet, uint32_t *num, uint8_t *more, +int coap_get_header_block2(coap_message_t *message, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset); -int coap_set_header_block2(void *packet, uint32_t num, uint8_t more, +int coap_set_header_block2(coap_message_t *message, uint32_t num, uint8_t more, uint16_t size); -int coap_get_header_block1(void *packet, uint32_t *num, uint8_t *more, +int coap_get_header_block1(coap_message_t *message, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset); -int coap_set_header_block1(void *packet, uint32_t num, uint8_t more, +int coap_set_header_block1(coap_message_t *message, uint32_t num, uint8_t more, uint16_t size); -int coap_get_header_size2(void *packet, uint32_t *size); -int coap_set_header_size2(void *packet, uint32_t size); +int coap_get_header_size2(coap_message_t *message, uint32_t *size); +int coap_set_header_size2(coap_message_t *message, uint32_t size); -int coap_get_header_size1(void *packet, uint32_t *size); -int coap_set_header_size1(void *packet, uint32_t size); +int coap_get_header_size1(coap_message_t *message, uint32_t *size); +int coap_set_header_size1(coap_message_t *message, uint32_t size); -int coap_get_payload(void *packet, const uint8_t **payload); -int coap_set_payload(void *packet, const void *payload, size_t length); +int coap_get_payload(coap_message_t *message, const uint8_t **payload); +int coap_set_payload(coap_message_t *message, const void *payload, size_t length); -#endif /* ER_COAP_H_ */ +#endif /* COAP_H_ */ +/** @} */ +/** @} */ diff --git a/os/net/app-layer/coap/rest-constants.h b/os/net/app-layer/coap/rest-constants.h deleted file mode 100644 index addc0970b004b3ff809419ec54e9e85bc3ef787b..0000000000000000000000000000000000000000 --- a/os/net/app-layer/coap/rest-constants.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - */ - -/** - * \file - * Constants for the REST Engine (Erbium). - * \author - * Matthias Kovatsch <kovatsch@inf.ethz.ch> - */ - -#ifndef REST_CONSTANTS_H_ -#define REST_CONSTANTS_H_ - -/** - * Generic status codes that are mapped to either HTTP or CoAP codes. - */ -struct rest_implementation_status { - const unsigned int OK; /* CONTENT_2_05, OK_200 */ - const unsigned int CREATED; /* CREATED_2_01, CREATED_201 */ - const unsigned int CHANGED; /* CHANGED_2_04, NO_CONTENT_204 */ - const unsigned int DELETED; /* DELETED_2_02, NO_CONTENT_204 */ - const unsigned int NOT_MODIFIED; /* VALID_2_03, NOT_MODIFIED_304 */ - - const unsigned int BAD_REQUEST; /* BAD_REQUEST_4_00, BAD_REQUEST_400 */ - const unsigned int UNAUTHORIZED; /* UNAUTHORIZED_4_01, UNAUTHORIZED_401 */ - const unsigned int BAD_OPTION; /* BAD_OPTION_4_02, BAD_REQUEST_400 */ - const unsigned int FORBIDDEN; /* FORBIDDEN_4_03, FORBIDDEN_403 */ - const unsigned int NOT_FOUND; /* NOT_FOUND_4_04, NOT_FOUND_404 */ - const unsigned int METHOD_NOT_ALLOWED; /* METHOD_NOT_ALLOWED_4_05, METHOD_NOT_ALLOWED_405 */ - const unsigned int NOT_ACCEPTABLE; /* NOT_ACCEPTABLE_4_06, NOT_ACCEPTABLE_406 */ - const unsigned int REQUEST_ENTITY_TOO_LARGE; /* REQUEST_ENTITY_TOO_LARGE_4_13, REQUEST_ENTITY_TOO_LARGE_413 */ - const unsigned int UNSUPPORTED_MEDIA_TYPE; /* UNSUPPORTED_MEDIA_TYPE_4_15, UNSUPPORTED_MEDIA_TYPE_415 */ - - const unsigned int INTERNAL_SERVER_ERROR; /* INTERNAL_SERVER_ERROR_5_00, INTERNAL_SERVER_ERROR_500 */ - const unsigned int NOT_IMPLEMENTED; /* NOT_IMPLEMENTED_5_01, NOT_IMPLEMENTED_501 */ - const unsigned int BAD_GATEWAY; /* BAD_GATEWAY_5_02, BAD_GATEWAY_502 */ - const unsigned int SERVICE_UNAVAILABLE; /* SERVICE_UNAVAILABLE_5_03, SERVICE_UNAVAILABLE_503 */ - const unsigned int GATEWAY_TIMEOUT; /* GATEWAY_TIMEOUT_5_04, GATEWAY_TIMEOUT_504 */ - const unsigned int PROXYING_NOT_SUPPORTED; /* PROXYING_NOT_SUPPORTED_5_05, INTERNAL_SERVER_ERROR_500 */ -}; - -/** - * List of Content-Formats which are Internet Media Types plus encoding. - * TODO This should be a constant enum taken from CoAP for both CoAP and HTTP. - */ -struct rest_implementation_type { - unsigned int TEXT_PLAIN; - unsigned int TEXT_XML; - unsigned int TEXT_CSV; - unsigned int TEXT_HTML; - unsigned int IMAGE_GIF; - unsigned int IMAGE_JPEG; - unsigned int IMAGE_PNG; - unsigned int IMAGE_TIFF; - unsigned int AUDIO_RAW; - unsigned int VIDEO_RAW; - unsigned int APPLICATION_LINK_FORMAT; - unsigned int APPLICATION_XML; - unsigned int APPLICATION_OCTET_STREAM; - unsigned int APPLICATION_RDF_XML; - unsigned int APPLICATION_SOAP_XML; - unsigned int APPLICATION_ATOM_XML; - unsigned int APPLICATION_XMPP_XML; - unsigned int APPLICATION_EXI; - unsigned int APPLICATION_FASTINFOSET; - unsigned int APPLICATION_SOAP_FASTINFOSET; - unsigned int APPLICATION_JSON; - unsigned int APPLICATION_X_OBIX_BINARY; -}; - -/** - * Resource flags for allowed methods and special functionalities. - */ -typedef enum { - NO_FLAGS = 0, - - /* methods to handle */ - METHOD_GET = (1 << 0), - METHOD_POST = (1 << 1), - METHOD_PUT = (1 << 2), - METHOD_DELETE = (1 << 3), - - /* special flags */ - HAS_SUB_RESOURCES = (1 << 4), - IS_SEPARATE = (1 << 5), - IS_OBSERVABLE = (1 << 6), - IS_PERIODIC = (1 << 7) -} rest_resource_flags_t; - -#endif /* REST_CONSTANTS_H_ */ diff --git a/os/net/app-layer/coap/rest-engine.c b/os/net/app-layer/coap/rest-engine.c deleted file mode 100644 index cec590012448438a6d095927cf75d70e6e095293..0000000000000000000000000000000000000000 --- a/os/net/app-layer/coap/rest-engine.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - */ - -/** - * \file - * An abstraction layer for RESTful Web services (Erbium). - * Inspired by RESTful Contiki by Dogan Yazar. - * \author - * Matthias Kovatsch <kovatsch@inf.ethz.ch> - */ - -#include <string.h> -#include <stdio.h> -#include "contiki.h" -#include "rest-engine.h" - -#define DEBUG 0 -#if DEBUG -#include <stdio.h> -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif - -PROCESS(rest_engine_process, "REST Engine"); -/*---------------------------------------------------------------------------*/ -LIST(restful_services); -LIST(restful_periodic_services); -/*---------------------------------------------------------------------------*/ -/*- REST Engine API ---------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -/** - * \brief Initializes and starts the REST Engine process - * - * This function must be called by server processes before any resources are - * registered through rest_activate_resource(). - */ -void -rest_init_engine(void) -{ - /* avoid initializing twice */ - static uint8_t initialized = 0; - - if(initialized) { - PRINTF("REST engine process already running - double initialization?\n"); - return; - } - initialized = 1; - - list_init(restful_services); - - REST.set_service_callback(rest_invoke_restful_service); - - /* Start the RESTful server implementation. */ - REST.init(); - - /*Start REST engine process */ - process_start(&rest_engine_process, NULL); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Makes a resource available under the given URI path - * \param resource A pointer to a resource implementation - * \param path The URI path string for this resource - * - * The resource implementation must be imported first using the - * extern keyword. The build system takes care of compiling every - * *.c file in the ./resources/ sub-directory (see example Makefile). - */ -void -rest_activate_resource(resource_t *resource, char *path) -{ - resource->url = path; - list_add(restful_services, resource); - - PRINTF("Activating: %s\n", resource->url); - - /* Only add periodic resources with a periodic_handler and a period > 0. */ - if(resource->flags & IS_PERIODIC && resource->periodic->periodic_handler - && resource->periodic->period) { - PRINTF("Periodic resource: %p (%s)\n", resource->periodic, - resource->periodic->resource->url); - list_add(restful_periodic_services, resource->periodic); - if(process_is_running(&rest_engine_process)) { - PRINTF("Periodic: Set timer for /%s to %lu\n", - resource->url, resource->periodic->period); - PROCESS_CONTEXT_BEGIN(&rest_engine_process); - etimer_set(&resource->periodic->periodic_timer, - resource->periodic->period); - PROCESS_CONTEXT_END(&rest_engine_process); - } - } -} -/*---------------------------------------------------------------------------*/ -/*- Internal API ------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -list_t -rest_get_resources(void) -{ - return restful_services; -} -/*---------------------------------------------------------------------------*/ -int -rest_invoke_restful_service(void *request, void *response, uint8_t *buffer, - uint16_t buffer_size, int32_t *offset) -{ - uint8_t found = 0; - uint8_t allowed = 1; - - resource_t *resource = NULL; - const char *url = NULL; - int url_len, res_url_len; - - url_len = REST.get_url(request, &url); - for(resource = (resource_t *)list_head(restful_services); - resource; resource = resource->next) { - - /* if the web service handles that kind of requests and urls matches */ - res_url_len = strlen(resource->url); - if((url_len == res_url_len - || (url_len > res_url_len - && (resource->flags & HAS_SUB_RESOURCES) - && url[res_url_len] == '/')) - && strncmp(resource->url, url, res_url_len) == 0) { - found = 1; - rest_resource_flags_t method = REST.get_method_type(request); - - PRINTF("/%s, method %u, resource->flags %u\n", resource->url, - (uint16_t)method, resource->flags); - - if((method & METHOD_GET) && resource->get_handler != NULL) { - /* call handler function */ - resource->get_handler(request, response, buffer, buffer_size, offset); - } else if((method & METHOD_POST) && resource->post_handler != NULL) { - /* call handler function */ - resource->post_handler(request, response, buffer, buffer_size, - offset); - } else if((method & METHOD_PUT) && resource->put_handler != NULL) { - /* call handler function */ - resource->put_handler(request, response, buffer, buffer_size, offset); - } else if((method & METHOD_DELETE) && resource->delete_handler != NULL) { - /* call handler function */ - resource->delete_handler(request, response, buffer, buffer_size, - offset); - } else { - allowed = 0; - REST.set_response_status(response, REST.status.METHOD_NOT_ALLOWED); - } - break; - } - } - if(!found) { - REST.set_response_status(response, REST.status.NOT_FOUND); - } else if(allowed) { - /* final handler for special flags */ - if(resource->flags & IS_OBSERVABLE) { - REST.subscription_handler(resource, request, response); - } - } - return found & allowed; -} -/*-----------------------------------------------------------------------------------*/ -PROCESS_THREAD(rest_engine_process, ev, data) -{ - PROCESS_BEGIN(); - - /* pause to let REST server finish adding resources. */ - PROCESS_PAUSE(); - - /* initialize the PERIODIC_RESOURCE timers, which will be handled by this process. */ - periodic_resource_t *periodic_resource = NULL; - - for(periodic_resource = - (periodic_resource_t *)list_head(restful_periodic_services); - periodic_resource; periodic_resource = periodic_resource->next) { - if(periodic_resource->periodic_handler && periodic_resource->period) { - PRINTF("Periodic: Set timer for /%s to %lu\n", - periodic_resource->resource->url, periodic_resource->period); - etimer_set(&periodic_resource->periodic_timer, - periodic_resource->period); - } - } - while(1) { - PROCESS_WAIT_EVENT(); - - if(ev == PROCESS_EVENT_TIMER) { - for(periodic_resource = - (periodic_resource_t *)list_head(restful_periodic_services); - periodic_resource; periodic_resource = periodic_resource->next) { - if(periodic_resource->period - && etimer_expired(&periodic_resource->periodic_timer)) { - - PRINTF("Periodic: etimer expired for /%s (period: %lu)\n", - periodic_resource->resource->url, periodic_resource->period); - - /* Call the periodic_handler function, which was checked during adding to list. */ - (periodic_resource->periodic_handler)(); - - etimer_reset(&periodic_resource->periodic_timer); - } - } - } - } - - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ diff --git a/os/net/app-layer/coap/rest-engine.h b/os/net/app-layer/coap/rest-engine.h deleted file mode 100644 index cf9faa7344a2dddf29b08bb2c15cc4b95bca162f..0000000000000000000000000000000000000000 --- a/os/net/app-layer/coap/rest-engine.h +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - */ - -/** - * \file - * An abstraction layer for RESTful Web services (Erbium). - * Inspired by RESTful Contiki by Dogan Yazar. - * \author - * Matthias Kovatsch <kovatsch@inf.ethz.ch> - */ - -#ifndef REST_ENGINE_H_ -#define REST_ENGINE_H_ - -#include <stdio.h> -#include "contiki.h" -#include "contiki-lib.h" -#include "rest-constants.h" - -/* NOTE: this will be removed - now it is always set to erbium CoAP implementation */ -#define REST coap_rest_implementation - -/* - * The maximum buffer size that is provided for resource responses and must be respected due to the limited IP buffer. - * Larger data must be handled by the resource and will be sent chunk-wise through a TCP stream or CoAP blocks. - */ -#ifndef REST_MAX_CHUNK_SIZE -#define REST_MAX_CHUNK_SIZE 64 -#endif - -struct resource_s; -struct periodic_resource_s; - -/* signatures of handler functions */ -typedef void (*restful_handler)(void *request, void *response, - uint8_t *buffer, uint16_t preferred_size, - int32_t *offset); -typedef void (*restful_final_handler)(struct resource_s *resource, - void *request, void *response); -typedef void (*restful_periodic_handler)(void); -typedef void (*restful_response_handler)(void *data, void *response); -typedef void (*restful_trigger_handler)(void); - -/* signature of the rest-engine service function */ -typedef int (*service_callback_t)(void *request, void *response, - uint8_t *buffer, uint16_t preferred_size, - int32_t *offset); - -/* data structure representing a resource in REST */ -struct resource_s { - struct resource_s *next; /* for LIST, points to next resource defined */ - const char *url; /*handled URL */ - rest_resource_flags_t flags; /* handled RESTful methods */ - const char *attributes; /* link-format attributes */ - restful_handler get_handler; /* handler function */ - restful_handler post_handler; /* handler function */ - restful_handler put_handler; /* handler function */ - restful_handler delete_handler; /* handler function */ - union { - struct periodic_resource_s *periodic; /* special data depending on flags */ - restful_trigger_handler trigger; - restful_trigger_handler resume; - }; -}; -typedef struct resource_s resource_t; - -struct periodic_resource_s { - struct periodic_resource_s *next; /* for LIST, points to next resource defined */ - const resource_t *resource; - uint32_t period; - struct etimer periodic_timer; - const restful_periodic_handler periodic_handler; -}; -typedef struct periodic_resource_s periodic_resource_t; - -/* - * Macro to define a RESTful resource. - * Resources are statically defined for the sake of efficiency and better memory management. - */ -#define RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \ - resource_t name = { NULL, NULL, NO_FLAGS, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } } - -#define PARENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \ - resource_t name = { NULL, NULL, HAS_SUB_RESOURCES, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } } - -#define SEPARATE_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, resume_handler) \ - resource_t name = { NULL, NULL, IS_SEPARATE, attributes, get_handler, post_handler, put_handler, delete_handler, { .resume = resume_handler } } - -#define EVENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, event_handler) \ - resource_t name = { NULL, NULL, IS_OBSERVABLE, attributes, get_handler, post_handler, put_handler, delete_handler, { .trigger = event_handler } } - -/* - * Macro to define a periodic resource. - * The corresponding [name]_periodic_handler() function will be called every period. - * For instance polling a sensor and publishing a changed value to subscribed clients would be done there. - * The subscriber list will be maintained by the final_handler rest_subscription_handler() (see rest-mapping header file). - */ -#define PERIODIC_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, period, periodic_handler) \ - periodic_resource_t periodic_##name; \ - resource_t name = { NULL, NULL, IS_OBSERVABLE | IS_PERIODIC, attributes, get_handler, post_handler, put_handler, delete_handler, { .periodic = &periodic_##name } }; \ - periodic_resource_t periodic_##name = { NULL, &name, period, { { 0 } }, periodic_handler }; - -struct rest_implementation { - char *name; - - /** Initialize the REST implementation. */ - void (*init)(void); - - /** Register the RESTful service callback at implementation. */ - void (*set_service_callback)(service_callback_t callback); - - /** Get request URI path. */ - int (*get_url)(void *request, const char **url); - - /** Get the method of a request. */ - rest_resource_flags_t (*get_method_type)(void *request); - - /** Set the status code of a response. */ - int (*set_response_status)(void *response, unsigned int code); - - /** Get the content-type of a request. */ - int (*get_header_content_type)(void *request, - unsigned int *content_format); - - /** Set the Content-Type of a response. */ - int (*set_header_content_type)(void *response, - unsigned int content_format); - - /** Get the Accept types of a request. */ - int (*get_header_accept)(void *request, unsigned int *accept); - - /** Get the Length option of a request. */ - int (*get_header_length)(void *request, uint32_t *size); - - /** Set the Length option of a response. */ - int (*set_header_length)(void *response, uint32_t size); - - /** Get the Max-Age option of a request. */ - int (*get_header_max_age)(void *request, uint32_t *age); - - /** Set the Max-Age option of a response. */ - int (*set_header_max_age)(void *response, uint32_t age); - - /** Set the ETag option of a response. */ - int (*set_header_etag)(void *response, const uint8_t *etag, - size_t length); - - /** Get the If-Match option of a request. */ - int (*get_header_if_match)(void *request, const uint8_t **etag); - - /** Get the If-Match option of a request. */ - int (*get_header_if_none_match)(void *request); - - /** Get the Host option of a request. */ - int (*get_header_host)(void *request, const char **host); - - /** Set the location option of a response. */ - int (*set_header_location)(void *response, const char *location); - - /** Get the payload option of a request. */ - int (*get_request_payload)(void *request, const uint8_t **payload); - - /** Set the payload option of a response. */ - int (*set_response_payload)(void *response, const void *payload, - size_t length); - - /** Get the query string of a request. */ - int (*get_query)(void *request, const char **value); - - /** Get the value of a request query key-value pair. */ - int (*get_query_variable)(void *request, const char *name, - const char **value); - - /** Get the value of a request POST key-value pair. */ - int (*get_post_variable)(void *request, const char *name, - const char **value); - - /** Send the payload to all subscribers of the resource at url. */ - void (*notify_subscribers)(resource_t *resource); - - /** The handler for resource subscriptions. */ - restful_final_handler subscription_handler; - - /* REST status codes. */ - const struct rest_implementation_status status; - - /* REST content-types. */ - const struct rest_implementation_type type; -}; - -/* instance of REST implementation */ -extern const struct rest_implementation REST; - -/* - * To be called by HTTP/COAP server as a callback function when a new service request appears. - * This function dispatches the corresponding RESTful service. - */ -int rest_invoke_restful_service(void *request, void *response, - uint8_t *buffer, uint16_t buffer_size, - int32_t *offset); -/*---------------------------------------------------------------------------*/ -/** - * \brief Initializes REST framework and starts the HTTP or CoAP process. - */ -void rest_init_engine(void); -/*---------------------------------------------------------------------------*/ -/** - * - * \brief Resources wanted to be accessible should be activated with the following code. - * \param resource - * A RESTful resource defined through the RESOURCE macros. - * \param path - * The local URI path where to provide the resource. - */ -void rest_activate_resource(resource_t *resource, char *path); -/*---------------------------------------------------------------------------*/ -/** - * \brief Returns the list of registered RESTful resources. - * \return The resource list. - */ -list_t rest_get_resources(void); -/*---------------------------------------------------------------------------*/ - -#endif /*REST_ENGINE_H_ */ diff --git a/os/net/app-layer/coap/tinydtls-support/Makefile.tinydtls-support b/os/net/app-layer/coap/tinydtls-support/Makefile.tinydtls-support new file mode 100644 index 0000000000000000000000000000000000000000..ac8a5aff45700d5f0c038ef006546456d61ebdb2 --- /dev/null +++ b/os/net/app-layer/coap/tinydtls-support/Makefile.tinydtls-support @@ -0,0 +1 @@ +${info Building with tinyDTLS - see $(CONTIKI)/$(TINYDTLS_PATH)/LICENSE} diff --git a/os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h b/os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h new file mode 100644 index 0000000000000000000000000000000000000000..9265583e588e5527a6fe3ff484f381ade92fe13c --- /dev/null +++ b/os/net/app-layer/coap/tinydtls-support/dtls-support-conf.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017, RISE SICS AB. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * DTLS support for CoAP + * \author + * Niclas Finne <nfi@sics.se> + * Joakim Eriksson <joakime@sics.se> + */ + +#ifndef DTLS_SUPPORT_CONF_H_ +#define DTLS_SUPPORT_CONF_H_ + +/* Use same log level as CoAP as default */ +#define LOG_LEVEL_DTLS LOG_LEVEL_COAP + +#define DTLS_LOG_CONF_PATH "coap-log.h" + +#include "coap-endpoint.h" + +typedef coap_endpoint_t session_t; + +#include "sys/ctimer.h" +#include <stdint.h> + +typedef struct { + struct ctimer retransmit_timer; +} dtls_support_context_state_t; + +#define DTLS_SUPPORT_CONF_CONTEXT_STATE dtls_support_context_state_t + +#define DTLS_TICKS_PER_SECOND CLOCK_SECOND + +typedef clock_time_t dtls_tick_t; + +#define HAVE_ASSERT_H 1 + +#endif /* DTLS_SUPPORT_CONF_H_ */ diff --git a/os/net/app-layer/coap/tinydtls-support/dtls-support.c b/os/net/app-layer/coap/tinydtls-support/dtls-support.c new file mode 100644 index 0000000000000000000000000000000000000000..4675c76d0fc697e813b271396211ff5346425aa6 --- /dev/null +++ b/os/net/app-layer/coap/tinydtls-support/dtls-support.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2017, RISE SICS AB. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * DTLS support for CoAP + * \author + * Niclas Finne <nfi@sics.se> + * Joakim Eriksson <joakime@sics.se> + */ + +#include "dtls-support.h" +#include "lib/random.h" +#include <stdio.h> +#include <stdarg.h> + +/* Log configuration */ +#define LOG_MODULE "dtls" +#define LOG_LEVEL LOG_LEVEL_DTLS +#include "dtls-log.h" +#include "coap-log.h" + +static dtls_context_t the_dtls_context; +static dtls_cipher_context_t cipher_context; +static uint8_t lock_context = 0; +/*---------------------------------------------------------------------------*/ +dtls_context_t * +dtls_context_acquire(void) +{ + if(lock_context) { + return NULL; + } + lock_context = 1; + LOG_DBG("Allocated context\n"); + return &the_dtls_context; +} +/*---------------------------------------------------------------------------*/ +void +dtls_context_release(dtls_context_t *context) +{ + if(context == &the_dtls_context) { + lock_context = 0; + } +} +/*---------------------------------------------------------------------------*/ +dtls_cipher_context_t * +dtls_cipher_context_acquire(void) +{ + return &cipher_context; +} +/*---------------------------------------------------------------------------*/ +void +dtls_cipher_context_release(dtls_cipher_context_t *c) +{ +} +/*---------------------------------------------------------------------------*/ +void +dtls_ticks(dtls_tick_t *t) +{ + *t = clock_time(); +} +/*---------------------------------------------------------------------------*/ +int +dtls_fill_random(uint8_t *buf, size_t len) +{ + int i; + if(buf) { + for(i = 0; i < len; i++) { + buf[i] = random_rand() & 0xff; + } + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* message retransmission */ +/*---------------------------------------------------------------------------*/ +static void +dtls_retransmit_callback(void *ptr) +{ + dtls_context_t *ctx; + clock_time_t now; + clock_time_t next; + + ctx = ptr; + now = clock_time(); + /* Just one retransmission per timer scheduling */ + dtls_check_retransmit(ctx, &next, 0); + + /* need to set timer to some value even if no nextpdu is available */ + if(next != 0) { + ctimer_set(&ctx->support.retransmit_timer, + next <= now ? 1 : next - now, + dtls_retransmit_callback, ctx); + } +} +/*---------------------------------------------------------------------------*/ +void +dtls_set_retransmit_timer(dtls_context_t *ctx, unsigned int timeout) +{ + ctimer_set(&ctx->support.retransmit_timer, timeout, + dtls_retransmit_callback, ctx); +} +/*---------------------------------------------------------------------------*/ +void +dtls_session_init(session_t *sess) +{ + memset(sess, 0, sizeof(session_t)); +} +/*---------------------------------------------------------------------------*/ +int +dtls_session_equals(const session_t *a, const session_t *b) +{ + coap_endpoint_t *e1 = (coap_endpoint_t *)a; + coap_endpoint_t *e2 = (coap_endpoint_t *)b; + + if(LOG_DBG_ENABLED) { + LOG_DBG(" **** EP:"); + LOG_DBG_COAP_EP(e1); + LOG_DBG_(" =?= "); + LOG_DBG_COAP_EP(e2); + LOG_DBG_(" => %d\n", coap_endpoint_cmp(e1, e2)); + } + + return coap_endpoint_cmp(e1, e2); +} +/*---------------------------------------------------------------------------*/ +void * +dtls_session_get_address(const session_t *a) +{ + /* improve this to only contain the addressing info */ + return (void *)a; +} +/*---------------------------------------------------------------------------*/ +int dtls_session_get_address_size(const session_t *a) +{ + /* improve this to only contain the addressing info */ + return sizeof(session_t); +} +/*---------------------------------------------------------------------------*/ +void +dtls_session_print(const session_t *a) +{ + coap_endpoint_print((const coap_endpoint_t *)a); +} +/*---------------------------------------------------------------------------*/ +void +dtls_session_log(const session_t *a) +{ + coap_endpoint_log((const coap_endpoint_t *)a); +} +/*---------------------------------------------------------------------------*/ +void +dtls_support_init(void) +{ + LOG_INFO("init\n"); +} +/*---------------------------------------------------------------------------*/ diff --git a/os/net/app-layer/http-socket/http-socket.h b/os/net/app-layer/http-socket/http-socket.h index 5b683e10ba12928938cb88be0b6d258a01fb60ad..adac80c3e83f33080119f1a9010eacef225745e3 100644 --- a/os/net/app-layer/http-socket/http-socket.h +++ b/os/net/app-layer/http-socket/http-socket.h @@ -32,6 +32,7 @@ #define HTTP_SOCKET_H #include "tcp-socket.h" +#include "sys/cc.h" struct http_socket; @@ -62,8 +63,6 @@ typedef void (* http_socket_callback_t)(struct http_socket *s, const uint8_t *data, uint16_t datalen); -#define MAX(n, m) (((n) < (m)) ? (m) : (n)) - #define HTTP_SOCKET_INPUTBUFSIZE UIP_TCP_MSS #define HTTP_SOCKET_OUTPUTBUFSIZE MAX(UIP_TCP_MSS, 128) diff --git a/os/net/ipv6/multicast/esmrf.c b/os/net/ipv6/multicast/esmrf.c index 2da8da4004baef8d3f19bbbce80c68b60a4b48f3..00619c35491a46f43fa758b6dff84c3d602756c2 100644 --- a/os/net/ipv6/multicast/esmrf.c +++ b/os/net/ipv6/multicast/esmrf.c @@ -46,15 +46,16 @@ #include "net/ipv6/multicast/uip-mcast6-route.h" #include "net/ipv6/multicast/uip-mcast6-stats.h" #include "net/ipv6/multicast/esmrf.h" -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ +#include "net/routing/routing.h" #include "net/ipv6/uip.h" #include "net/netstack.h" #include "net/packetbuf.h" +#if ROUTING_CONF_RPL_LITE +#include "net/routing/rpl-lite/rpl.h" +#endif /* ROUTING_CONF_RPL_LITE */ +#if ROUTING_CONF_RPL_CLASSIC +#include "net/routing/rpl-classic/rpl.h" +#endif /* ROUTING_CONF_RPL_CLASSIC */ #include <string.h> extern uint16_t uip_slen; @@ -229,7 +230,7 @@ icmp_input() uip_process(UIP_UDP_SEND_CONN); - memcpy(&mcast_buf, uip_buf, uip_len); + memcpy(&mcast_buf, &uip_buf[UIP_LLH_LEN], uip_len); mcast_len = uip_len; /* pass the packet to our uip_process to check if it is allowed to * accept this packet or not */ @@ -239,7 +240,7 @@ icmp_input() uip_process(UIP_DATA); - memcpy(uip_buf, &mcast_buf, mcast_len); + memcpy(&uip_buf[UIP_LLH_LEN], &mcast_buf, mcast_len); uip_len = mcast_len; /* Return the IP of the original Multicast sender */ uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &src_ip); @@ -257,7 +258,7 @@ icmp_input() static void mcast_fwd(void *p) { - memcpy(uip_buf, &mcast_buf, mcast_len); + memcpy(&uip_buf[UIP_LLH_LEN], &mcast_buf, mcast_len); uip_len = mcast_len; UIP_IP_BUF->ttl--; tcpip_output(NULL); @@ -291,7 +292,7 @@ in() parent_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(parent_ipaddr); if(parent_lladdr == NULL) { - PRINTF("ESMRF: NO Parent exist \n"); + PRINTF("ESMRF: No Parent found\n"); UIP_MCAST6_STATS_ADD(mcast_dropped); return UIP_MCAST6_DROP; } @@ -309,6 +310,7 @@ in() if(UIP_IP_BUF->ttl <= 1) { UIP_MCAST6_STATS_ADD(mcast_dropped); + PRINTF("ESMRF: TTL too low\n"); return UIP_MCAST6_DROP; } @@ -350,12 +352,14 @@ in() fwd_delay = fwd_delay * (1 + ((random_rand() >> 11) % fwd_spread)); } - memcpy(&mcast_buf, uip_buf, uip_len); + memcpy(&mcast_buf, &uip_buf[UIP_LLH_LEN], uip_len); mcast_len = uip_len; ctimer_set(&mcast_periodic, fwd_delay, mcast_fwd, NULL); } PRINTF("ESMRF: %u bytes: fwd in %u [%u]\n", uip_len, fwd_delay, fwd_spread); + } else { + PRINTF("ESMRF: Group unknown, dropping\n"); } /* Done with this packet unless we are a member of the mcast group */ diff --git a/os/net/ipv6/multicast/roll-tm.c b/os/net/ipv6/multicast/roll-tm.c index edf86b22bbc069f212ad51703ecbc1c28e2ac82d..1d19512d6c4af7d428e0278a4a108678277df686 100644 --- a/os/net/ipv6/multicast/roll-tm.c +++ b/os/net/ipv6/multicast/roll-tm.c @@ -1321,7 +1321,7 @@ static void out() { - if(uip_len + HBHO_TOTAL_LEN > UIP_BUFSIZE) { + if(uip_len + HBHO_TOTAL_LEN > UIP_BUFSIZE - UIP_LLH_LEN) { PRINTF("ROLL TM: Multicast Out can not add HBHO. Packet too long\n"); goto drop; } diff --git a/os/net/ipv6/multicast/smrf.c b/os/net/ipv6/multicast/smrf.c index 06167f75ac5a1d17375db9004987c60d9a6a53c9..86a05364833710a68b5c74d8e6d249b159914283 100644 --- a/os/net/ipv6/multicast/smrf.c +++ b/os/net/ipv6/multicast/smrf.c @@ -47,13 +47,15 @@ #include "net/ipv6/multicast/uip-mcast6-route.h" #include "net/ipv6/multicast/uip-mcast6-stats.h" #include "net/ipv6/multicast/smrf.h" -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ +#include "net/routing/routing.h" #include "net/netstack.h" #include "net/packetbuf.h" +#if ROUTING_CONF_RPL_LITE +#include "net/routing/rpl-lite/rpl.h" +#endif /* ROUTING_CONF_RPL_LITE */ +#if ROUTING_CONF_RPL_CLASSIC +#include "net/routing/rpl-classic/rpl.h" +#endif /* ROUTING_CONF_RPL_CLASSIC */ #include <string.h> #define DEBUG DEBUG_NONE @@ -82,7 +84,7 @@ static uint8_t fwd_spread; static void mcast_fwd(void *p) { - memcpy(uip_buf, &mcast_buf, mcast_len); + memcpy(&uip_buf[UIP_LLH_LEN], &mcast_buf, mcast_len); uip_len = mcast_len; UIP_IP_BUF->ttl--; tcpip_output(NULL); @@ -106,6 +108,7 @@ in() */ d = rpl_get_any_dag(); if(!d) { + PRINTF("SMRF: No DODAG\n"); UIP_MCAST6_STATS_ADD(mcast_dropped); return UIP_MCAST6_DROP; } @@ -115,6 +118,7 @@ in() parent_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(parent_ipaddr); if(parent_lladdr == NULL) { + PRINTF("SMRF: No Parent found\n"); UIP_MCAST6_STATS_ADD(mcast_dropped); return UIP_MCAST6_DROP; } @@ -132,6 +136,7 @@ in() if(UIP_IP_BUF->ttl <= 1) { UIP_MCAST6_STATS_ADD(mcast_dropped); + PRINTF("SMRF: TTL too low\n"); return UIP_MCAST6_DROP; } @@ -173,12 +178,14 @@ in() fwd_delay = fwd_delay * (1 + ((random_rand() >> 11) % fwd_spread)); } - memcpy(&mcast_buf, uip_buf, uip_len); + memcpy(&mcast_buf, &uip_buf[UIP_LLH_LEN], uip_len); mcast_len = uip_len; ctimer_set(&mcast_periodic, fwd_delay, mcast_fwd, NULL); } PRINTF("SMRF: %u bytes: fwd in %u [%u]\n", uip_len, fwd_delay, fwd_spread); + } else { + PRINTF("SMRF: Group unknown, dropping\n"); } /* Done with this packet unless we are a member of the mcast group */ diff --git a/os/net/ipv6/resolv.h b/os/net/ipv6/resolv.h index ed24d5bceef2d0bcd6d156a4a1980671d6919556..ac414425f515bfd8c5447890a6e74a08a71e27c4 100644 --- a/os/net/ipv6/resolv.h +++ b/os/net/ipv6/resolv.h @@ -55,7 +55,7 @@ /** * Event that is broadcasted when a DNS name has been resolved. */ -CCIF extern process_event_t resolv_event_found; +extern process_event_t resolv_event_found; enum { /** Hostname is fresh and usable. This response is cached and will eventually @@ -91,14 +91,14 @@ enum { typedef uint8_t resolv_status_t; /* Functions. */ -CCIF resolv_status_t resolv_lookup(const char *name, uip_ipaddr_t ** ipaddr); +resolv_status_t resolv_lookup(const char *name, uip_ipaddr_t ** ipaddr); -CCIF void resolv_query(const char *name); +void resolv_query(const char *name); #if RESOLV_CONF_SUPPORTS_MDNS -CCIF void resolv_set_hostname(const char *hostname); +void resolv_set_hostname(const char *hostname); -CCIF const char *resolv_get_hostname(void); +const char *resolv_get_hostname(void); #endif PROCESS_NAME(resolv_process); diff --git a/os/net/ipv6/sicslowpan.c b/os/net/ipv6/sicslowpan.c index 2f239f77e05d4ad771d8bbc5337d3e5f4889feca..4e3e4e00c275ee35426e1ac8f21c9d02659d17d9 100644 --- a/os/net/ipv6/sicslowpan.c +++ b/os/net/ipv6/sicslowpan.c @@ -68,17 +68,13 @@ #include "net/ipv6/tcpip.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" +#include "net/ipv6/uipbuf.h" #include "net/ipv6/sicslowpan.h" #include "net/netstack.h" #include "net/packetbuf.h" #include "net/queuebuf.h" -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ +#include "net/routing/routing.h" /* Log configuration */ #include "sys/log.h" @@ -101,6 +97,7 @@ /* define the buffer as a byte array */ #define PACKETBUF_IPHC_BUF ((uint8_t *)(packetbuf_ptr + packetbuf_hdr_len)) +#define PACKETBUF_PAYLOAD_END ((uint8_t *)(packetbuf_ptr + mac_max_payload)) #define PACKETBUF_6LO_PTR (packetbuf_ptr + packetbuf_hdr_len) #define PACKETBUF_6LO_DISPATCH 0 /* 8 bit */ @@ -122,7 +119,7 @@ /* NOTE: In the multiple-reassembly context there is only room for the header / first fragment */ #define SICSLOWPAN_IP_BUF(buf) ((struct uip_ip_hdr *)buf) #define SICSLOWPAN_UDP_BUF(buf) ((struct uip_udp_hdr *)&buf[UIP_IPH_LEN]) -#define SICSLOWPAN_IPPAYLOAD_BUF(buf) (&buf[UIP_LLIPH_LEN]) +#define SICSLOWPAN_IPPAYLOAD_BUF(buf) (&buf[UIP_IPH_LEN]) #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) @@ -201,6 +198,11 @@ static int packetbuf_payload_len; */ static uint8_t uncomp_hdr_len; +/** + * mac_max_payload is the maimum payload space on the MAC frame. + */ +static int mac_max_payload; + /** * The current page (RFC 4944) */ @@ -357,7 +359,7 @@ add_fragment(uint16_t tag, uint16_t frag_size, uint8_t offset) for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) { /* clear all fragment info with expired timer to free all fragment buffers */ if(frag_info[i].len > 0 && timer_expired(&frag_info[i].reass_timer)) { - clear_fragments(i); + clear_fragments(i); } /* We use len as indication on used or not used */ @@ -425,12 +427,12 @@ copy_frags2uip(int context) /* Copy from the fragment context info buffer first */ memcpy((uint8_t *)UIP_IP_BUF, (uint8_t *)frag_info[context].first_frag, - frag_info[context].first_frag_len); + frag_info[context].first_frag_len); for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) { /* And also copy all matching fragments */ if(frag_buf[i].len > 0 && frag_buf[i].index == context) { memcpy((uint8_t *)UIP_IP_BUF + (uint16_t)(frag_buf[i].offset << 3), - (uint8_t *)frag_buf[i].data, frag_buf[i].len); + (uint8_t *)frag_buf[i].data, frag_buf[i].len); } } /* deallocate all the fragments for this context */ @@ -667,26 +669,42 @@ uncompress_addr(uip_ipaddr_t *ipaddr, uint8_t const prefix[], * compress the IID. * \param link_destaddr L2 destination address, needed to compress IP * dest + * \return 1 if success, else 0 */ -static void +static int compress_hdr_iphc(linkaddr_t *link_destaddr) { uint8_t tmp, iphc0, iphc1, *next_hdr, *next_nhc; int ext_hdr_len; struct uip_udp_hdr *udp_buf; -#if LOG_DBG_ENABLED - { uint16_t ndx; + if(LOG_DBG_ENABLED) { + uint16_t ndx; LOG_DBG("before compression (%d): ", UIP_IP_BUF->len[1]); for(ndx = 0; ndx < UIP_IP_BUF->len[1] + 40; ndx++) { uint8_t data = ((uint8_t *) (UIP_IP_BUF))[ndx]; - LOG_DBG("%02x", data); + LOG_DBG_("%02x", data); } - LOG_DBG("\n"); + LOG_DBG_("\n"); } -#endif /* LOG_DBG_ENABLED */ + +/* Macro used only internally, during header compression. Checks if there + * is sufficient space in packetbuf before writing any further. */ +#define CHECK_BUFFER_SPACE(writelen) do { \ + if(hc06_ptr + (writelen) >= PACKETBUF_PAYLOAD_END) { \ + LOG_WARN("Not enough packetbuf space to compress header (%u bytes, %u left). Aborting.\n", \ + (unsigned)(writelen), (unsigned)(PACKETBUF_PAYLOAD_END - hc06_ptr)); \ + return 0; \ + } \ +} while(0); hc06_ptr = PACKETBUF_IPHC_BUF + 2; + + /* Check if there is enough space for the compressed IPv6 header, in the + * worst case (least compressed case). Extension headers and transport + * layer will be checked when they are compressed. */ + CHECK_BUFFER_SPACE(38); + /* * As we copy some bit-length fields, in the IPHC encoding bytes, * we sometimes use |= @@ -915,11 +933,13 @@ compress_hdr_iphc(linkaddr_t *link_destaddr) NHC byte extra - before the next header here. This is due to next not being elided in that case. */ if(!IS_COMPRESSABLE_PROTO(*next_hdr)) { + CHECK_BUFFER_SPACE(1); hc06_ptr++; LOG_INFO("Keeping the next header in this ext hdr: %d\n", ext_hdr->next); } /* copy the ext-hdr into the hc06 buffer */ + CHECK_BUFFER_SPACE(len); memcpy(hc06_ptr, ext_hdr, len); /* modify the len to octets */ ext_hdr = (struct uip_ext_hdr *) hc06_ptr; @@ -949,6 +969,7 @@ compress_hdr_iphc(linkaddr_t *link_destaddr) /* we can compress 12 bits of both source and dest */ *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_11; LOG_INFO("IPHC: remove 12 b of both source & dest with prefix 0xFOB\n"); + CHECK_BUFFER_SPACE(1); *hc06_ptr = (uint8_t)((UIP_HTONS(udp_buf->srcport) - SICSLOWPAN_UDP_4_BIT_PORT_MIN) << 4) + @@ -959,6 +980,7 @@ compress_hdr_iphc(linkaddr_t *link_destaddr) /* we can compress 8 bits of dest, leave source. */ *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_01; LOG_INFO("IPHC: leave source, remove 8 bits of dest with prefix 0xF0\n"); + CHECK_BUFFER_SPACE(3); memcpy(hc06_ptr, &udp_buf->srcport, 2); *(hc06_ptr + 2) = (uint8_t)((UIP_HTONS(udp_buf->destport) - @@ -968,6 +990,7 @@ compress_hdr_iphc(linkaddr_t *link_destaddr) /* we can compress 8 bits of src, leave dest. Copy compressed port */ *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_10; LOG_INFO("IPHC: remove 8 bits of source with prefix 0xF0, leave dest. hch: %i\n", *next_nhc); + CHECK_BUFFER_SPACE(3); *hc06_ptr = (uint8_t)((UIP_HTONS(udp_buf->srcport) - SICSLOWPAN_UDP_8_BIT_PORT_MIN)); @@ -977,10 +1000,12 @@ compress_hdr_iphc(linkaddr_t *link_destaddr) /* we cannot compress. Copy uncompressed ports, full checksum */ *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_00; LOG_INFO("IPHC: cannot compress UDP headers\n"); + CHECK_BUFFER_SPACE(4); memcpy(hc06_ptr, &udp_buf->srcport, 4); hc06_ptr += 4; } /* always inline the checksum */ + CHECK_BUFFER_SPACE(2); memcpy(hc06_ptr, &udp_buf->udpchksum, 2); hc06_ptr += 2; uncomp_hdr_len += UIP_UDPH_LEN; @@ -1000,18 +1025,19 @@ compress_hdr_iphc(linkaddr_t *link_destaddr) PACKETBUF_IPHC_BUF[0] = iphc0; PACKETBUF_IPHC_BUF[1] = iphc1; -#if LOG_DBG_ENABLED - { uint16_t ndx; + if(LOG_DBG_ENABLED) { + uint16_t ndx; LOG_DBG("after compression %d: ", (int)(hc06_ptr - packetbuf_ptr)); for(ndx = 0; ndx < hc06_ptr - packetbuf_ptr; ndx++) { uint8_t data = ((uint8_t *) packetbuf_ptr)[ndx]; - LOG_DBG("%02x", data); + LOG_DBG_("%02x", data); } - LOG_DBG("\n"); - } -#endif + LOG_DBG_("\n"); + } packetbuf_hdr_len = hc06_ptr - packetbuf_ptr; + + return 1; } /*--------------------------------------------------------------------*/ @@ -1065,7 +1091,7 @@ uncompress_hdr_iphc(uint8_t *buf, uint16_t ip_len) SICSLOWPAN_IP_BUF(buf)->vtc = 0x60 | ((tmp >> 2) & 0x0f); /* ECN rolled down two steps + lowest DSCP bits at top two bits */ SICSLOWPAN_IP_BUF(buf)->tcflow = ((tmp >> 2) & 0x30) | (tmp << 6) | - (SICSLOWPAN_IP_BUF(buf)->tcflow & 0x0f); + (SICSLOWPAN_IP_BUF(buf)->tcflow & 0x0f); } else { /* Traffic class is compressed (set version and no TC)*/ SICSLOWPAN_IP_BUF(buf)->vtc = 0x60; @@ -1080,7 +1106,7 @@ uncompress_hdr_iphc(uint8_t *buf, uint16_t ip_len) /* Version and flow label are compressed */ if((iphc0 & SICSLOWPAN_IPHC_TC_C) == 0) { /* Traffic class is inline */ - SICSLOWPAN_IP_BUF(buf)->vtc = 0x60 | ((*hc06_ptr >> 2) & 0x0f); + SICSLOWPAN_IP_BUF(buf)->vtc = 0x60 | ((*hc06_ptr >> 2) & 0x0f); SICSLOWPAN_IP_BUF(buf)->tcflow = ((*hc06_ptr << 6) & 0xC0) | ((*hc06_ptr >> 2) & 0x30); SICSLOWPAN_IP_BUF(buf)->flow = 0; hc06_ptr += 1; @@ -1435,10 +1461,8 @@ packet_sent(void *ptr, int status, int transmissions) /* Update neighbor link statistics */ link_stats_packet_sent(dest, status, transmissions); -#if UIP_CONF_IPV6_RPL - /* Call RPL link callback */ - rpl_link_callback(dest, status, transmissions); -#endif /* UIP_CONF_IPV6_RPL */ + /* Call routing protocol link callback */ + NETSTACK_ROUTING.link_callback(dest, status, transmissions); /* DS6 callback, used for UIP_DS6_LL_NUD */ uip_ds6_link_callback(status, transmissions); @@ -1485,7 +1509,6 @@ static uint8_t output(const linkaddr_t *localdest) { int framer_hdrlen; - int max_payload; /* The MAC address of the destination of the packet */ linkaddr_t dest; @@ -1517,6 +1540,24 @@ output(const linkaddr_t *localdest) LOG_INFO("output: sending packet len %d\n", uip_len); + /* copy over the retransmission count from uipbuf attributes */ + packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, + uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS)); + +/* Calculate NETSTACK_FRAMER's header length, that will be added in the NETSTACK_MAC */ +#ifndef SICSLOWPAN_USE_FIXED_HDRLEN + packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest); + framer_hdrlen = NETSTACK_FRAMER.length(); + if(framer_hdrlen < 0) { + /* Framing failed, we assume the maximum header length */ + framer_hdrlen = SICSLOWPAN_FIXED_HDRLEN; + } +#else /* USE_FRAMER_HDRLEN */ + framer_hdrlen = SICSLOWPAN_FIXED_HDRLEN; +#endif /* USE_FRAMER_HDRLEN */ + + mac_max_payload = MAC_MAX_PAYLOAD - framer_hdrlen; + /* Try to compress the headers */ #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6 compress_hdr_ipv6(&dest); @@ -1530,26 +1571,14 @@ output(const linkaddr_t *localdest) } #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH */ #if SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC - compress_hdr_iphc(&dest); + if(compress_hdr_iphc(&dest) == 0) { + /* Warning should already be issued by function above */ + return 0; + } #endif /* SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC */ LOG_INFO("output: header of len %d\n", packetbuf_hdr_len); - /* Calculate NETSTACK_FRAMER's header length, that will be added in the NETSTACK_MAC. - * We calculate it here only to make a better decision of whether the outgoing packet - * needs to be fragmented or not. */ -#ifndef SICSLOWPAN_USE_FIXED_HDRLEN - packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest); - framer_hdrlen = NETSTACK_FRAMER.length(); - if(framer_hdrlen < 0) { - /* Framing failed, we assume the maximum header length */ - framer_hdrlen = SICSLOWPAN_FIXED_HDRLEN; - } -#else /* USE_FRAMER_HDRLEN */ - framer_hdrlen = SICSLOWPAN_FIXED_HDRLEN; -#endif /* USE_FRAMER_HDRLEN */ - - max_payload = MAC_MAX_PAYLOAD - framer_hdrlen; - if((int)uip_len - (int)uncomp_hdr_len > max_payload - (int)packetbuf_hdr_len) { + if((int)uip_len - (int)uncomp_hdr_len > mac_max_payload - (int)packetbuf_hdr_len) { #if SICSLOWPAN_CONF_FRAG /* Number of bytes processed. */ uint16_t processed_ip_out_len; @@ -1564,7 +1593,7 @@ output(const linkaddr_t *localdest) * IPv6/IPHC/HC_UDP dispatchs/headers. * The following fragments contain only the fragn dispatch. */ - int estimated_fragments = ((int)uip_len) / (max_payload - SICSLOWPAN_FRAGN_HDR_LEN) + 1; + int estimated_fragments = ((int)uip_len) / (mac_max_payload - SICSLOWPAN_FRAGN_HDR_LEN) + 1; int freebuf = queuebuf_numfree() - 1; LOG_INFO("uip_len: %d, fragments: %d, free bufs: %d\n", uip_len, estimated_fragments, freebuf); if(freebuf < estimated_fragments) { @@ -1575,7 +1604,7 @@ output(const linkaddr_t *localdest) LOG_INFO("Fragmentation sending packet len %d\n", uip_len); /* Create 1st Fragment */ - LOG_INFO("output: 1rst fragment "); + LOG_INFO("output: 1st fragment "); /* Reset last tx status to ok in case the fragment transmissions are deferred */ last_tx_status = MAC_TX_OK; @@ -1594,8 +1623,17 @@ output(const linkaddr_t *localdest) /* Copy payload and send */ packetbuf_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN; - packetbuf_payload_len = (max_payload - packetbuf_hdr_len) & 0xfffffff8; - LOG_INFO("(len %d, tag %d)\n", packetbuf_payload_len, frag_tag); + packetbuf_payload_len = (mac_max_payload - packetbuf_hdr_len) & 0xfffffff8; + LOG_INFO_("(len %d, tag %d)\n", packetbuf_payload_len, frag_tag); + + if(packetbuf_payload_len < 0) { + /* The current implementation requires that all headers fit in the first + * fragment. Here is a corner case where the header did fit packetbuf + * but do no longer fit after truncating for a length multiple of 8. */ + LOG_WARN("compressed header does not fit first fragment\n"); + return 0; + } + memcpy(packetbuf_ptr + packetbuf_hdr_len, (uint8_t *)UIP_IP_BUF + uncomp_hdr_len, packetbuf_payload_len); packetbuf_set_datalen(packetbuf_payload_len + packetbuf_hdr_len); @@ -1630,7 +1668,7 @@ output(const linkaddr_t *localdest) /* uip_htons((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len); */ SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE, ((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len)); - packetbuf_payload_len = (max_payload - packetbuf_hdr_len) & 0xfffffff8; + packetbuf_payload_len = (mac_max_payload - packetbuf_hdr_len) & 0xfffffff8; while(processed_ip_out_len < uip_len) { LOG_INFO("output: fragment "); PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET] = processed_ip_out_len >> 3; @@ -1640,7 +1678,7 @@ output(const linkaddr_t *localdest) /* last fragment */ packetbuf_payload_len = uip_len - processed_ip_out_len; } - LOG_INFO("(offset %d, len %d, tag %d)\n", + LOG_INFO_("(offset %d, len %d, tag %d)\n", processed_ip_out_len >> 3, packetbuf_payload_len, frag_tag); memcpy(packetbuf_ptr + packetbuf_hdr_len, (uint8_t *)UIP_IP_BUF + processed_ip_out_len, packetbuf_payload_len); @@ -1746,7 +1784,7 @@ input(void) frag_offset = 0; frag_size = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff; frag_tag = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG); - LOG_INFO("size %d, tag %d, offset %d)\n", + LOG_INFO_ ("size %d, tag %d, offset %d)\n", frag_size, frag_tag, frag_offset); packetbuf_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN; first_fragment = 1; @@ -1771,13 +1809,13 @@ input(void) frag_offset = PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET]; frag_tag = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG); frag_size = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff; - LOG_INFO("size %d, tag %d, offset %d)\n", + LOG_INFO_("size %d, tag %d, offset %d)\n", frag_size, frag_tag, frag_offset); packetbuf_hdr_len += SICSLOWPAN_FRAGN_HDR_LEN; /* If this is the last fragment, we may shave off any extrenous bytes at the end. We must be liberal in what we accept. */ - LOG_INFO("last_fragment?: packetbuf_payload_len %d frag_size %d\n", + LOG_INFO_("last_fragment?: packetbuf_payload_len %d frag_size %d\n", packetbuf_datalen() - packetbuf_hdr_len, frag_size); /* Add the fragment to the fragmentation context (this will also @@ -1906,19 +1944,17 @@ input(void) uip_len = packetbuf_payload_len + uncomp_hdr_len; #endif /* SICSLOWPAN_CONF_FRAG */ LOG_INFO("input: IP packet ready (length %d)\n", - uip_len); + uip_len); -#if LOG_DBG_ENABLED - { + if(LOG_DBG_ENABLED) { uint16_t ndx; LOG_DBG("after decompression %u:", UIP_IP_BUF->len[1]); for (ndx = 0; ndx < UIP_IP_BUF->len[1] + 40; ndx++) { uint8_t data = ((uint8_t *) (UIP_IP_BUF))[ndx]; - LOG_DBG("%02x", data); + LOG_DBG_("%02x", data); } - LOG_DBG("\n"); + LOG_DBG_("\n"); } -#endif /* LOG_DBG_ENABLED */ /* if callback is set then set attributes and call */ if(callback) { diff --git a/os/net/ipv6/tcpip.c b/os/net/ipv6/tcpip.c index 32632090909c141c9587492380528df7ce5ba522..5db4b9a215dee36c46bce398ef120934e937c79b 100644 --- a/os/net/ipv6/tcpip.c +++ b/os/net/ipv6/tcpip.c @@ -38,21 +38,15 @@ * \author Julien Abeille <jabeille@cisco.com> (IPv6 related code) */ +#include "contiki.h" #include "contiki-net.h" #include "net/ipv6/uip-packetqueue.h" #include "net/ipv6/uip-nd6.h" #include "net/ipv6/uip-ds6.h" +#include "net/ipv6/uip-ds6-nbr.h" #include "net/linkaddr.h" - -#if UIP_CONF_IPV6_RPL -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#endif +#include "net/routing/routing.h" #include <string.h> @@ -103,11 +97,6 @@ enum { PACKET_INPUT }; -#if UIP_CONF_IPV6_RPL && RPL_WITH_NON_STORING -#define NEXTHOP_NON_STORING(addr) rpl_ext_header_srh_get_next_hop(addr) -#else -#define NEXTHOP_NON_STORING(addr) 0 -#endif /*---------------------------------------------------------------------------*/ static void init_appstate(uip_tcp_appstate_t *as, void *state) @@ -121,6 +110,19 @@ uint8_t tcpip_output(const uip_lladdr_t *a) { int ret; + + /* Tag Traffic Class if we are using TC for variable retrans */ +#if UIP_TAG_TC_WITH_VARIABLE_RETRANSMISSIONS + if(uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS) != + UIP_MAX_MAC_TRANSMISSIONS_UNDEFINED) { + LOG_INFO("Tagging TC with retrans: %d\n", uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS)); + /* Encapsulate the MAC transmission limit in the Traffic Class field */ + UIP_IP_BUF->vtc = 0x60 | (UIP_TC_MAC_TRANSMISSION_COUNTER_BIT >> 4); + UIP_IP_BUF->tcflow = + uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS) << 4; + } +#endif + if(netstack_process_ip_callback(NETSTACK_IP_OUTPUT, (const linkaddr_t *)a) == NETSTACK_IP_PROCESS) { ret = NETSTACK_NETWORK.output((const linkaddr_t *) a); @@ -166,7 +168,22 @@ static void packet_input(void) { if(uip_len > 0) { + LOG_INFO("input: received %u bytes\n", uip_len); + check_for_tcp_syn(); + +#if UIP_TAG_TC_WITH_VARIABLE_RETRANSMISSIONS + { + uint8_t traffic_class = (UIP_IP_BUF->vtc << 4) | (UIP_IP_BUF->tcflow >> 4); + if(traffic_class & UIP_TC_MAC_TRANSMISSION_COUNTER_BIT) { + uint8_t max_mac_transmissions = traffic_class & UIP_TC_MAC_TRANSMISSION_COUNTER_MASK; + uipbuf_set_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS, max_mac_transmissions); + LOG_INFO("Received packet tagged with TC retrans: %d (%x)", + max_mac_transmissions, traffic_class); + } + } +#endif /* UIP_TAG_TC_WITH_VARIABLE_RETRANSMISSIONS */ + uip_input(); if(uip_len > 0) { tcpip_ipv6_output(); @@ -446,12 +463,7 @@ output_fallback(void) #ifdef UIP_FALLBACK_INTERFACE LOG_INFO("fallback: removing ext hdrs & setting proto %d %d\n", uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40)); - if(uip_ext_len > 0) { - uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40); - remove_ext_hdr(); - /* This should be copied from the ext header... */ - UIP_IP_BUF->proto = proto; - } + remove_ext_hdr(); /* Inform the other end that the destination is not reachable. If it's * not informed routes might get lost unexpectedly until there's a need * to send a new packet to the peer */ @@ -468,23 +480,6 @@ output_fallback(void) } /*---------------------------------------------------------------------------*/ static void -drop_route(uip_ds6_route_t *route) -{ -#if UIP_CONF_IPV6_RPL && (UIP_CONF_IPV6_RPL_LITE == 0) - - /* If we are running RPL, and if we are the root of the - network, we'll trigger a global repair before we remove - the route. */ - rpl_dag_t *dag; - dag = (rpl_dag_t *)route->state.dag; - if(dag != NULL && dag->instance != NULL) { - rpl_repair_root(dag->instance->instance_id); - } -#endif /* UIP_CONF_IPV6_RPL && (UIP_CONF_IPV6_RPL_LITE == 0) */ - uip_ds6_route_rm(route); -} -/*---------------------------------------------------------------------------*/ -static void annotate_transmission(uip_ipaddr_t *nexthop) { #if TCPIP_CONF_ANNOTATE_TRANSMISSIONS @@ -506,13 +501,13 @@ get_nexthop(uip_ipaddr_t *addr) uip_ipaddr_t *nexthop; uip_ds6_route_t *route; - LOG_INFO("output: processing packet from "); + LOG_INFO("output: processing %u bytes packet from ", uip_len); LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr); LOG_INFO_(" to "); LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr); LOG_INFO_("\n"); - if(NEXTHOP_NON_STORING(addr)) { + if(NETSTACK_ROUTING.ext_header_srh_get_next_hop(addr)) { LOG_INFO("output: selected next hop from SRH: "); LOG_INFO_6ADDR(addr); LOG_INFO_("\n"); @@ -550,9 +545,11 @@ get_nexthop(uip_ipaddr_t *addr) never responded to link-layer acks, we drop its route. */ if(nexthop == NULL) { LOG_ERR("output: found dead route\n"); - drop_route(route); - /* We don't have a nexthop to send the packet to, so we drop - it. */ + /* Notifiy the routing protocol that we are about to remove the route */ + NETSTACK_ROUTING.drop_route(route); + /* Remove the route */ + uip_ds6_route_rm(route); + /* We don't have a nexthop to send the packet to, so we drop it. */ } else { LOG_INFO("output: found next hop from routing table: "); LOG_INFO_6ADDR(nexthop); @@ -657,14 +654,13 @@ tcpip_ipv6_output(void) goto exit; } -#if UIP_CONF_IPV6_RPL - if(!rpl_ext_header_update()) { + + if(!NETSTACK_ROUTING.ext_header_update()) { /* Packet can not be forwarded */ - LOG_ERR("output: RPL header update error\n"); + LOG_ERR("output: routing protocol extension header update error\n"); uip_clear_buf(); return; } -#endif /* UIP_CONF_IPV6_RPL */ if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { linkaddr = NULL; @@ -834,10 +830,8 @@ PROCESS_THREAD(tcpip_process, ev, data) #ifdef UIP_FALLBACK_INTERFACE UIP_FALLBACK_INTERFACE.init(); #endif - /* initialize RPL if configured for using RPL */ -#if UIP_CONF_IPV6_RPL - rpl_init(); -#endif /* UIP_CONF_IPV6_RPL */ + /* Initialize routing protocol */ + NETSTACK_ROUTING.init(); while(1) { PROCESS_YIELD(); diff --git a/os/net/ipv6/tcpip.h b/os/net/ipv6/tcpip.h index bf8c9b0b1723a0414ecefd64b9e76626ade2d1f3..8f84cedb32f66ecbb187d3bd91fa2fae65b61284 100644 --- a/os/net/ipv6/tcpip.h +++ b/os/net/ipv6/tcpip.h @@ -108,8 +108,7 @@ void tcpip_uipcall(void); * process whenever an event occurs on the connection. * */ -CCIF void tcp_attach(struct uip_conn *conn, - void *appstate); +void tcp_attach(struct uip_conn *conn, void *appstate); #define tcp_markconn(conn, appstate) tcp_attach(conn, appstate) /** @@ -126,7 +125,7 @@ CCIF void tcp_attach(struct uip_conn *conn, * \param port The port number in network byte order. * */ -CCIF void tcp_listen(uint16_t port); +void tcp_listen(uint16_t port); /** * Close a listening TCP port. @@ -140,7 +139,7 @@ CCIF void tcp_listen(uint16_t port); * \param port The port number in network byte order. * */ -CCIF void tcp_unlisten(uint16_t port); +void tcp_unlisten(uint16_t port); /** * Open a TCP connection to the specified IP address and port. @@ -165,8 +164,8 @@ CCIF void tcp_unlisten(uint16_t port); * memory could not be allocated for the connection. * */ -CCIF struct uip_conn *tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port, - void *appstate); +struct uip_conn *tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port, + void *appstate); /** * Cause a specified TCP connection to be polled. @@ -226,8 +225,8 @@ void udp_attach(struct uip_udp_conn *conn, * \return A pointer to the newly created connection, or NULL if * memory could not be allocated for the connection. */ -CCIF struct uip_udp_conn *udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, - void *appstate); +struct uip_udp_conn *udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, + void *appstate); /** * Create a new UDP broadcast connection. @@ -272,7 +271,7 @@ struct uip_udp_conn *udp_broadcast_new(uint16_t port, void *appstate); * \param conn A pointer to the UDP connection that should be polled. * */ -CCIF void tcpip_poll_udp(struct uip_udp_conn *conn); +void tcpip_poll_udp(struct uip_udp_conn *conn); /** @} */ @@ -288,7 +287,7 @@ CCIF void tcpip_poll_udp(struct uip_udp_conn *conn); * * This event is posted to a process whenever a uIP ICMP event has occurred. */ -CCIF extern process_event_t tcpip_icmp6_event; +extern process_event_t tcpip_icmp6_event; /** * \brief register an ICMPv6 callback @@ -318,7 +317,7 @@ void tcpip_icmp6_call(uint8_t type); * * This event is posted to a process whenever a uIP event has occurred. */ -CCIF extern process_event_t tcpip_event; +extern process_event_t tcpip_event; /** @@ -335,7 +334,7 @@ CCIF extern process_event_t tcpip_event; * and the length of the packet must be in the global * uip_len variable. */ -CCIF void tcpip_input(void); +void tcpip_input(void); /** * \brief Output packet to layer 2 diff --git a/os/net/ipv6/uip-debug.c b/os/net/ipv6/uip-debug.c deleted file mode 100755 index f83f0ee5b5630bb8601101b539cc4e5c86c18358..0000000000000000000000000000000000000000 --- a/os/net/ipv6/uip-debug.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -/** - * \file - * A set of debugging tools for the IP stack - * \author - * Nicolas Tsiftes <nvt@sics.se> - * Niclas Finne <nfi@sics.se> - * Joakim Eriksson <joakime@sics.se> - */ - -#include "net/ipv6/uip-debug.h" -#include "net/ipv6/ip64-addr.h" - -/*---------------------------------------------------------------------------*/ -void -uip_debug_ipaddr_print(const uip_ipaddr_t *addr) -{ - uint16_t a; - unsigned int i; - int f; - - if(addr == NULL) { - PRINTA("(NULL IP addr)"); - return; - } - - if(ip64_addr_is_ipv4_mapped_addr(addr)) { - /* - * Printing IPv4-mapped addresses is done according to RFC 4291 [1] - * - * "An alternative form that is sometimes more - * convenient when dealing with a mixed environment - * of IPv4 and IPv6 nodes is x:x:x:x:x:x:d.d.d.d, - * where the 'x's are the hexadecimal values of the - * six high-order 16-bit pieces of the address, and - * the 'd's are the decimal values of the four - * low-order 8-bit pieces of the address (standard - * IPv4 representation)." - * - * [1] https://tools.ietf.org/html/rfc4291#page-4 - */ - PRINTA("::FFFF:%u.%u.%u.%u", addr->u8[12], addr->u8[13], addr->u8[14], addr->u8[15]); - } else { - for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { - a = (addr->u8[i] << 8) + addr->u8[i + 1]; - if(a == 0 && f >= 0) { - if(f++ == 0) { - PRINTA("::"); - } - } else { - if(f > 0) { - f = -1; - } else if(i > 0) { - PRINTA(":"); - } - PRINTA("%x", a); - } - } - } -} -/*---------------------------------------------------------------------------*/ diff --git a/os/net/ipv6/uip-debug.h b/os/net/ipv6/uip-debug.h index 267a36acacf739abb1063e329eac9f2c60abc972..6ebbf0aaa6eb4da69addd521d0321d12ed3b3565 100644 --- a/os/net/ipv6/uip-debug.h +++ b/os/net/ipv6/uip-debug.h @@ -43,13 +43,16 @@ #define UIP_DEBUG_H #include "net/net-debug.h" -#include "net/ipv6/uip.h" -#include <stdio.h> +#include "net/ipv6/uiplib.h" -void uip_debug_ipaddr_print(const uip_ipaddr_t *addr); +static inline void +uip_debug_ipaddr_print(const uip_ipaddr_t *addr) +{ + uiplib_ipaddr_print(addr); +} #if (DEBUG) & DEBUG_PRINT -#define PRINT6ADDR(addr) uip_debug_ipaddr_print(addr) +#define PRINT6ADDR(addr) uiplib_ipaddr_print(addr) #else #define PRINT6ADDR(addr) #endif /* (DEBUG) & DEBUG_PRINT */ diff --git a/os/net/ipv6/uip-ds6-nbr.c b/os/net/ipv6/uip-ds6-nbr.c index d07f85d78101f0a0895d66d4d5dba2f56893c163..e4912554812eb2d4bedb0d05408505b68b4ed4a4 100644 --- a/os/net/ipv6/uip-ds6-nbr.c +++ b/os/net/ipv6/uip-ds6-nbr.c @@ -50,20 +50,16 @@ #include "net/link-stats.h" #include "net/linkaddr.h" #include "net/packetbuf.h" +#include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip-ds6-nbr.h" +#include "net/ipv6/uip-nd6.h" +#include "net/routing/routing.h" /* Log configuration */ #include "sys/log.h" #define LOG_MODULE "IPv6 Nbr" #define LOG_LEVEL LOG_LEVEL_IPV6 -#ifdef UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED -#define NEIGHBOR_STATE_CHANGED(n) UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED(n) -void NEIGHBOR_STATE_CHANGED(uip_ds6_nbr_t *n); -#else -#define NEIGHBOR_STATE_CHANGED(n) -#endif /* UIP_DS6_CONF_NEIGHBOR_STATE_CHANGED */ - NBR_TABLE_GLOBAL(uip_ds6_nbr_t, ds6_neighbors); /*---------------------------------------------------------------------------*/ @@ -105,7 +101,7 @@ uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr, LOG_INFO_(" link addr "); LOG_INFO_LLADDR((linkaddr_t*)lladdr); LOG_INFO_(" state %u\n", state); - NEIGHBOR_STATE_CHANGED(nbr); + NETSTACK_ROUTING.neighbor_state_changed(nbr); return nbr; } else { LOG_INFO("Add drop ip addr "); @@ -125,7 +121,7 @@ uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr) #if UIP_CONF_IPV6_QUEUE_PKT uip_packetqueue_free(&nbr->packethandle); #endif /* UIP_CONF_IPV6_QUEUE_PKT */ - NEIGHBOR_STATE_CHANGED(nbr); + NETSTACK_ROUTING.neighbor_state_changed(nbr); return nbr_table_remove(ds6_neighbors, nbr); } return 0; @@ -257,7 +253,7 @@ uip_ds6_neighbor_periodic(void) switch(nbr->state) { case NBR_REACHABLE: if(stimer_expired(&nbr->reachable)) { -#if UIP_CONF_IPV6_RPL +#if UIP_CONF_ROUTER /* when a neighbor leave its REACHABLE state and is a default router, instead of going to STALE state it enters DELAY state in order to force a NUD on it. Otherwise, if there is no upward traffic, the @@ -277,12 +273,12 @@ uip_ds6_neighbor_periodic(void) LOG_INFO_(")\n"); nbr->state = NBR_STALE; } -#else /* UIP_CONF_IPV6_RPL */ +#else /* UIP_CONF_ROUTER */ LOG_INFO("REACHABLE: moving to STALE ("); LOG_INFO_6ADDR(&nbr->ipaddr); LOG_INFO_(")\n"); nbr->state = NBR_STALE; -#endif /* UIP_CONF_IPV6_RPL */ +#endif /* UIP_CONF_ROUTER */ } break; case NBR_INCOMPLETE: diff --git a/os/net/ipv6/uip-ds6-nbr.h b/os/net/ipv6/uip-ds6-nbr.h index ebb7de2d8195485ddd1933f6145c44f056885e93..9aec47b4ad1023c5479b8550c6a94944327443d9 100644 --- a/os/net/ipv6/uip-ds6-nbr.h +++ b/os/net/ipv6/uip-ds6-nbr.h @@ -46,10 +46,11 @@ #ifndef UIP_DS6_NEIGHBOR_H_ #define UIP_DS6_NEIGHBOR_H_ +#include "contiki.h" #include "net/ipv6/uip.h" +#include "net/ipv6/uip-nd6.h" #include "net/nbr-table.h" #include "sys/stimer.h" -#include "net/ipv6/uip-ds6.h" #if UIP_CONF_IPV6_QUEUE_PKT #include "net/ipv6/uip-packetqueue.h" #endif /*UIP_CONF_QUEUE_PKT */ diff --git a/os/net/ipv6/uip-ds6-route.c b/os/net/ipv6/uip-ds6-route.c index 9321b632cd360f0a23ae29b3f32f86a7a9df9385..a8fdd88fb0cb6a865c2c0ff37f66687f474d7dc0 100644 --- a/os/net/ipv6/uip-ds6-route.c +++ b/os/net/ipv6/uip-ds6-route.c @@ -103,7 +103,6 @@ LIST(notificationlist); #endif /*---------------------------------------------------------------------------*/ -#if LOG_DBG_ENABLED static void assert_nbr_routes_list_sane(void) { @@ -131,7 +130,6 @@ assert_nbr_routes_list_sane(void) } #endif /* (UIP_MAX_ROUTES != 0) */ } -#endif /* LOG_DBG_ENABLED */ /*---------------------------------------------------------------------------*/ #if UIP_DS6_NOTIFICATIONS static void @@ -330,9 +328,9 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, uip_ds6_route_t *r; struct uip_ds6_route_neighbor_route *nbrr; -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } if(ipaddr == NULL || nexthop == NULL) { return NULL; @@ -473,9 +471,9 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_ADD, ipaddr, nexthop); #endif -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } return r; #else /* (UIP_MAX_ROUTES != 0) */ @@ -489,9 +487,11 @@ uip_ds6_route_rm(uip_ds6_route_t *route) { #if (UIP_MAX_ROUTES != 0) struct uip_ds6_route_neighbor_route *neighbor_route; -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } + if(route != NULL && route->neighbor_routes != NULL) { LOG_INFO("Rm: removing route: "); @@ -541,9 +541,9 @@ uip_ds6_route_rm(uip_ds6_route_t *route) #endif } -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } #endif /* (UIP_MAX_ROUTES != 0) */ return; @@ -553,9 +553,10 @@ uip_ds6_route_rm(uip_ds6_route_t *route) static void rm_routelist(struct uip_ds6_route_neighbor_routes *routes) { -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } + if(routes != NULL && routes->route_list != NULL) { struct uip_ds6_route_neighbor_route *r; r = list_head(routes->route_list); @@ -565,9 +566,10 @@ rm_routelist(struct uip_ds6_route_neighbor_routes *routes) } nbr_table_remove(nbr_routes, routes); } -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } } /*---------------------------------------------------------------------------*/ static void @@ -603,9 +605,9 @@ uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval) { uip_ds6_defrt_t *d; -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } if(ipaddr == NULL) { return NULL; @@ -643,9 +645,9 @@ uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval) call_route_callback(UIP_DS6_NOTIFICATION_DEFRT_ADD, ipaddr, ipaddr); #endif -#if LOG_DBG_ENABLED +if(LOG_DBG_ENABLED) { assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ +} return d; } @@ -655,9 +657,9 @@ uip_ds6_defrt_rm(uip_ds6_defrt_t *defrt) { uip_ds6_defrt_t *d; -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } /* Make sure that the defrt is in the list before we remove it. */ for(d = list_head(defaultrouterlist); @@ -675,10 +677,10 @@ uip_ds6_defrt_rm(uip_ds6_defrt_t *defrt) return; } } -#if LOG_DBG_ENABLED - assert_nbr_routes_list_sane(); -#endif /* LOG_DBG_ENABLED */ + if(LOG_DBG_ENABLED) { + assert_nbr_routes_list_sane(); + } } /*---------------------------------------------------------------------------*/ uip_ds6_defrt_t * diff --git a/os/net/ipv6/uip-ds6-route.h b/os/net/ipv6/uip-ds6-route.h index acc417670986555f6d6d9e93bf9d444e39943a8a..9f435824cd8c14863658b1e29d3ccfa0fea317d2 100644 --- a/os/net/ipv6/uip-ds6-route.h +++ b/os/net/ipv6/uip-ds6-route.h @@ -44,22 +44,28 @@ #include "net/nbr-table.h" #include "sys/stimer.h" #include "lib/list.h" -#if UIP_CONF_IPV6_RPL -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl-conf.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl-conf.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#endif #ifdef UIP_CONF_MAX_ROUTES + #define UIP_MAX_ROUTES UIP_CONF_MAX_ROUTES + #else /* UIP_CONF_MAX_ROUTES */ + +#if ROUTING_CONF_RPL_LITE +#define UIP_MAX_ROUTES 0 /* RPL Lite only supports non-storing, no routes */ +#elif ROUTING_CONF_RPL_CLASSIC + +#include "net/routing/rpl-classic/rpl-conf.h" #if RPL_WITH_STORING #define UIP_MAX_ROUTES NETSTACK_MAX_ROUTE_ENTRIES -#else -#define UIP_MAX_ROUTES 0 +#else /* RPL_WITH_STORING */ +#define UIP_MAX_ROUTES 0 /* No storing mode, no need for routes */ +#endif /* RPL_WITH_STORING */ + +#else /* Not RPL Lite nor RPL Classic */ +#define UIP_MAX_ROUTES NETSTACK_MAX_ROUTE_ENTRIES #endif + #endif /* UIP_CONF_MAX_ROUTES */ NBR_TABLE_DECLARE(nbr_routes); diff --git a/os/net/ipv6/uip-ds6.c b/os/net/ipv6/uip-ds6.c index 18e9d33e90909fa1697e70eea93f255b0e4c2f1d..6dd178dc855671268b9bb7586048ed420bde6b8e 100644 --- a/os/net/ipv6/uip-ds6.c +++ b/os/net/ipv6/uip-ds6.c @@ -47,6 +47,7 @@ #include <stddef.h> #include "lib/random.h" #include "net/ipv6/uip-nd6.h" +#include "net/ipv6/uip-ds6-nbr.h" #include "net/ipv6/uip-ds6.h" #include "net/ipv6/multicast/uip-mcast6.h" #include "net/ipv6/uip-packetqueue.h" diff --git a/os/net/ipv6/uip-ds6.h b/os/net/ipv6/uip-ds6.h index 736f9bfebf60123754130225ebaa28c0ca623d57..45394fec3f918311a4305779c99d486ffce1d0db 100644 --- a/os/net/ipv6/uip-ds6.h +++ b/os/net/ipv6/uip-ds6.h @@ -46,8 +46,8 @@ #include "sys/stimer.h" /* The size of uip_ds6_addr_t depends on UIP_ND6_DEF_MAXDADNS. Include uip-nd6.h to define it. */ #include "net/ipv6/uip-nd6.h" -#include "net/ipv6/uip-ds6-route.h" #include "net/ipv6/uip-ds6-nbr.h" +#include "net/ipv6/uip-ds6-route.h" /*--------------------------------------------------*/ /** Configuration. For all tables (Neighbor cache, Prefix List, Routing Table, @@ -226,13 +226,6 @@ typedef struct uip_ds6_maddr { uip_ipaddr_t ipaddr; } uip_ds6_maddr_t; -/* only define the callback if RPL is active */ -#if UIP_CONF_IPV6_RPL && (UIP_CONF_IPV6_RPL_LITE == 0) -#ifndef UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED -#define UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED rpl_ipv6_neighbor_callback -#endif /* UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED */ -#endif /* UIP_CONF_IPV6_RPL */ - /** \brief Interface structure (contains all the interface variables) */ typedef struct uip_ds6_netif { uint32_t link_mtu; diff --git a/os/net/ipv6/uip-icmp6.c b/os/net/ipv6/uip-icmp6.c index 0a48a134edc66d67a6d9ea6ff50a66e1f7fd2adc..be33a11019267d0b47650067e083d31e9ce95353 100644 --- a/os/net/ipv6/uip-icmp6.c +++ b/os/net/ipv6/uip-icmp6.c @@ -46,6 +46,7 @@ #include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip-icmp6.h" #include "contiki-default-conf.h" +#include "net/routing/routing.h" /* Log configuration */ #include "sys/log.h" @@ -58,15 +59,6 @@ #define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len]) #define UIP_FIRST_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[UIP_LLIPH_LEN]) -#if UIP_CONF_IPV6_RPL -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#endif /* UIP_CONF_IPV6_RPL */ - /** \brief temporary IP address */ static uip_ipaddr_t tmp_ipaddr; @@ -193,11 +185,8 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) { } } -#if UIP_CONF_IPV6_RPL - rpl_ext_header_remove(); -#else - uip_ext_len = 0; -#endif /* UIP_CONF_IPV6_RPL */ + /* Remove all extension headers related to the routing protocol in place */ + NETSTACK_ROUTING.ext_header_remove(); /* remember data of original packet before shifting */ uip_ipaddr_copy(&tmp_ipaddr, &UIP_IP_BUF->destipaddr); @@ -238,12 +227,8 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) { return; } } else { -#if UIP_CONF_ROUTER /* need to pick a source that corresponds to this node */ uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &tmp_ipaddr); -#else - uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &tmp_ipaddr); -#endif } UIP_ICMP_BUF->type = type; diff --git a/os/net/ipv6/uip-nd6.c b/os/net/ipv6/uip-nd6.c index 5c01de392113ef6adfee5b0201fd4c5545e0bae5..ce555ed53c09760f86b17e87fc7a3bf99cc2eb6f 100644 --- a/os/net/ipv6/uip-nd6.c +++ b/os/net/ipv6/uip-nd6.c @@ -115,7 +115,7 @@ static uip_ds6_nbr_t *nbr; /** Pointer to a nbr cache entry*/ static uip_ds6_addr_t *addr; /** Pointer to an interface address */ #endif /* UIP_ND6_SEND_NS || UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */ -#if UIP_ND6_SEND_NS || !UIP_CONF_ROUTER +#if UIP_ND6_SEND_NS || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER static uip_ds6_defrt_t *defrt; /** Pointer to a router list entry */ #endif /* UIP_ND6_SEND_NS || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */ @@ -973,7 +973,7 @@ ra_input(void) default: LOG_DBG("Updating timer of prefix "); LOG_DBG_6ADDR(&prefix->ipaddr); - LOG_DBG_(" new value %lu\n", uip_ntohl(nd6_opt_prefix_info->validlt)); + LOG_DBG_(" new value %"PRIu32"\n", uip_ntohl(nd6_opt_prefix_info->validlt)); stimer_set(&prefix->vlifetime, uip_ntohl(nd6_opt_prefix_info->validlt)); prefix->isinfinite = 0; @@ -999,7 +999,7 @@ ra_input(void) LOG_DBG("Updating timer of address "); LOG_DBG_6ADDR(&addr->ipaddr); LOG_DBG_(" new value %lu\n", - uip_ntohl(nd6_opt_prefix_info->validlt)); + (unsigned long)uip_ntohl(nd6_opt_prefix_info->validlt)); stimer_set(&addr->vlifetime, uip_ntohl(nd6_opt_prefix_info->validlt)); } else { @@ -1027,18 +1027,16 @@ ra_input(void) break; #if UIP_ND6_RA_RDNSS case UIP_ND6_OPT_RDNSS: - if(UIP_ND6_RA_BUF->flags_reserved & (UIP_ND6_O_FLAG << 6)) { - LOG_DBG("Processing RDNSS option\n"); - uint8_t naddr = (UIP_ND6_OPT_RDNSS_BUF->len - 1) / 2; - uip_ipaddr_t *ip = (uip_ipaddr_t *)(&UIP_ND6_OPT_RDNSS_BUF->ip); - LOG_DBG("got %d nameservers\n", naddr); - while(naddr-- > 0) { - LOG_DBG("nameserver: "); - LOG_DBG_6ADDR(ip); - LOG_DBG_(" lifetime: %lx\n", uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime)); - uip_nameserver_update(ip, uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime)); - ip++; - } + LOG_DBG("Processing RDNSS option\n"); + uint8_t naddr = (UIP_ND6_OPT_RDNSS_BUF->len - 1) / 2; + uip_ipaddr_t *ip = (uip_ipaddr_t *)(&UIP_ND6_OPT_RDNSS_BUF->ip); + LOG_DBG("got %d nameservers\n", naddr); + while(naddr-- > 0) { + LOG_DBG("nameserver: "); + LOG_DBG_6ADDR(ip); + LOG_DBG_(" lifetime: %"PRIx32"\n", uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime)); + uip_nameserver_update(ip, uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime)); + ip++; } break; #endif /* UIP_ND6_RA_RDNSS */ diff --git a/os/net/ipv6/uip-nd6.h b/os/net/ipv6/uip-nd6.h index 43b989490cd56f5a404667a898d4632fce1342f9..2c1e3226b1836e715e8a9d63297c73512d33f82e 100644 --- a/os/net/ipv6/uip-nd6.h +++ b/os/net/ipv6/uip-nd6.h @@ -118,7 +118,7 @@ be added regardless of their reachability and liveness. */ #define UIP_ND6_MIN_RA_INTERVAL UIP_CONF_ND6_MIN_RA_INTERVAL #endif #define UIP_ND6_M_FLAG 0 -#define UIP_ND6_O_FLAG (UIP_ND6_RA_RDNSS || UIP_ND6_RA_DNSSL) +#define UIP_ND6_O_FLAG 0 #ifndef UIP_CONF_ROUTER_LIFETIME #define UIP_ND6_ROUTER_LIFETIME 3 * UIP_ND6_MAX_RA_INTERVAL #else diff --git a/os/net/rpl-lite/rpl-ns.c b/os/net/ipv6/uip-sr.c similarity index 67% rename from os/net/rpl-lite/rpl-ns.c rename to os/net/ipv6/uip-sr.c index 1bd72f368d8ce9fc47fc869e9043290e20833501..15b12355217d4428c2b9f2494fc7ad3d17757e60 100644 --- a/os/net/rpl-lite/rpl-ns.c +++ b/os/net/ipv6/uip-sr.c @@ -30,55 +30,59 @@ */ /** - * \addtogroup rpl-lite + * \addtogroup uip * @{ * * \file - * RPL non-storing mode specific functions. Includes support for - * source routing. + * Source routing support * * \author Simon Duquennoy <simon.duquennoy@inria.fr> */ -#include "net/rpl-lite/rpl.h" +#include "contiki.h" +#include "net/ipv6/uip-sr.h" +#include "net/routing/routing.h" #include "lib/list.h" #include "lib/memb.h" /* Log configuration */ #include "sys/log.h" -#define LOG_MODULE "RPL" -#define LOG_LEVEL LOG_LEVEL_RPL +#define LOG_MODULE "IPv6 SR" +#define LOG_LEVEL LOG_LEVEL_IPV6 /* Total number of nodes */ static int num_nodes; /* Every known node in the network */ LIST(nodelist); -MEMB(nodememb, rpl_ns_node_t, RPL_NS_LINK_NUM); +MEMB(nodememb, uip_sr_node_t, UIP_SR_LINK_NUM); /*---------------------------------------------------------------------------*/ int -rpl_ns_num_nodes(void) +uip_sr_num_nodes(void) { return num_nodes; } /*---------------------------------------------------------------------------*/ static int -node_matches_address(const rpl_ns_node_t *node, const uip_ipaddr_t *addr) +node_matches_address(void *graph, const uip_sr_node_t *node, const uip_ipaddr_t *addr) { - return addr != NULL - && node != NULL - && !memcmp(addr, &curr_instance.dag.dag_id, 8) - && !memcmp(((const unsigned char *)addr) + 8, node->link_identifier, 8); + if(node == NULL || addr == NULL || graph != node->graph) { + return 0; + } else { + uip_ipaddr_t node_ipaddr; + NETSTACK_ROUTING.get_sr_node_ipaddr(&node_ipaddr, node); + return uip_ipaddr_cmp(&node_ipaddr, addr); + } } /*---------------------------------------------------------------------------*/ -rpl_ns_node_t * -rpl_ns_get_node(const uip_ipaddr_t *addr) +uip_sr_node_t * +uip_sr_get_node(void *graph, const uip_ipaddr_t *addr) { - rpl_ns_node_t *l; + uip_sr_node_t *l; for(l = list_head(nodelist); l != NULL; l = list_item_next(l)) { /* Compare prefix and node identifier */ - if(node_matches_address(l, addr)) { + if(node_matches_address(graph, l, addr)) { return l; } } @@ -86,11 +90,17 @@ rpl_ns_get_node(const uip_ipaddr_t *addr) } /*---------------------------------------------------------------------------*/ int -rpl_ns_is_addr_reachable(const uip_ipaddr_t *addr) +uip_sr_is_addr_reachable(void *graph, const uip_ipaddr_t *addr) { - int max_depth = RPL_NS_LINK_NUM; - rpl_ns_node_t *node = rpl_ns_get_node(addr); - rpl_ns_node_t *root_node = rpl_ns_get_node(&curr_instance.dag.dag_id); + int max_depth = UIP_SR_LINK_NUM; + uip_ipaddr_t root_ipaddr; + uip_sr_node_t *node; + uip_sr_node_t *root_node; + + NETSTACK_ROUTING.get_root_ipaddr(&root_ipaddr); + node = uip_sr_get_node(graph, addr); + root_node = uip_sr_get_node(graph, &root_ipaddr); + while(node != NULL && node != root_node && max_depth > 0) { node = node->parent; max_depth--; @@ -99,26 +109,26 @@ rpl_ns_is_addr_reachable(const uip_ipaddr_t *addr) } /*---------------------------------------------------------------------------*/ void -rpl_ns_expire_parent(const uip_ipaddr_t *child, const uip_ipaddr_t *parent) +uip_sr_expire_parent(void *graph, const uip_ipaddr_t *child, const uip_ipaddr_t *parent) { - rpl_ns_node_t *l = rpl_ns_get_node(child); + uip_sr_node_t *l = uip_sr_get_node(graph, child); /* Check if parent matches */ - if(l != NULL && node_matches_address(l->parent, parent)) { - l->lifetime = RPL_NOPATH_REMOVAL_DELAY; + if(l != NULL && node_matches_address(graph, l->parent, parent)) { + l->lifetime = UIP_SR_REMOVAL_DELAY; } } /*---------------------------------------------------------------------------*/ -rpl_ns_node_t * -rpl_ns_update_node(const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime) +uip_sr_node_t * +uip_sr_update_node(void *graph, const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime) { - rpl_ns_node_t *child_node = rpl_ns_get_node(child); - rpl_ns_node_t *parent_node = rpl_ns_get_node(parent); - rpl_ns_node_t *old_parent_node; + uip_sr_node_t *child_node = uip_sr_get_node(graph, child); + uip_sr_node_t *parent_node = uip_sr_get_node(graph, parent); + uip_sr_node_t *old_parent_node; if(parent != NULL) { /* No node for the parent, add one with infinite lifetime */ if(parent_node == NULL) { - parent_node = rpl_ns_update_node(parent, NULL, RPL_ROUTE_INFINITE_LIFETIME); + parent_node = uip_sr_update_node(graph, parent, NULL, UIP_SR_INFINITE_LIFETIME); if(parent_node == NULL) { LOG_ERR("NS: no space left for root node!\n"); return NULL; @@ -142,16 +152,17 @@ rpl_ns_update_node(const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32 } /* Initialize node */ + child_node->graph = graph; child_node->lifetime = lifetime; memcpy(child_node->link_identifier, ((const unsigned char *)child) + 8, 8); /* Is the node reachable before the update? */ - if(rpl_ns_is_addr_reachable(child)) { + if(uip_sr_is_addr_reachable(graph, child)) { old_parent_node = child_node->parent; /* Update node */ child_node->parent = parent_node; /* Has the node become unreachable? May happen if we create a loop. */ - if(!rpl_ns_is_addr_reachable(child)) { + if(!uip_sr_is_addr_reachable(graph, child)) { /* The new parent makes the node unreachable, restore old parent. * We will take the update next time, with chances we know more of * the topology and the loop is gone. */ @@ -171,79 +182,63 @@ rpl_ns_update_node(const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32 } /*---------------------------------------------------------------------------*/ void -rpl_ns_init(void) +uip_sr_init(void) { num_nodes = 0; memb_init(&nodememb); list_init(nodelist); } /*---------------------------------------------------------------------------*/ -rpl_ns_node_t * -rpl_ns_node_head(void) +uip_sr_node_t * +uip_sr_node_head(void) { return list_head(nodelist); } /*---------------------------------------------------------------------------*/ -rpl_ns_node_t * -rpl_ns_node_next(rpl_ns_node_t *item) +uip_sr_node_t * +uip_sr_node_next(uip_sr_node_t *item) { return list_item_next(item); } /*---------------------------------------------------------------------------*/ -int -rpl_ns_get_node_global_addr(uip_ipaddr_t *addr, rpl_ns_node_t *node) -{ - if(addr != NULL && node != NULL) { - memcpy(addr, &curr_instance.dag.dag_id, 8); - memcpy(((unsigned char *)addr) + 8, &node->link_identifier, 8); - return 1; - } else { - return 0; - } -} -/*---------------------------------------------------------------------------*/ void -rpl_ns_periodic(unsigned seconds) +uip_sr_periodic(unsigned seconds) { - rpl_ns_node_t *l; - rpl_ns_node_t *next; - /* First pass, decrement lifetime for all nodes with non-infinite lifetime */ - for(l = list_head(nodelist); l != NULL; l = list_item_next(l)) { - /* Don't touch infinite lifetime nodes */ - if(l->lifetime != RPL_ROUTE_INFINITE_LIFETIME) { - l->lifetime = l->lifetime > seconds ? l->lifetime - seconds : 0; - } - } - /* Second pass, for all expired nodes, deallocate them iff no child points to them */ + uip_sr_node_t *l; + uip_sr_node_t *next; + + /* First pass, for all expired nodes, deallocate them iff no child points to them */ for(l = list_head(nodelist); l != NULL; l = next) { next = list_item_next(l); if(l->lifetime == 0) { - rpl_ns_node_t *l2; + uip_sr_node_t *l2; for(l2 = list_head(nodelist); l2 != NULL; l2 = list_item_next(l2)) { if(l2->parent == l) { break; } } -#if LOG_INFO_ENABLED - uip_ipaddr_t node_addr; - rpl_ns_get_node_global_addr(&node_addr, l); - LOG_INFO("NS: removing expired node "); - LOG_INFO_6ADDR(&node_addr); - LOG_INFO_("\n"); -#endif /* LOG_INFO_ENABLED */ + if(LOG_INFO_ENABLED) { + uip_ipaddr_t node_addr; + NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, l); + LOG_INFO("NS: removing expired node "); + LOG_INFO_6ADDR(&node_addr); + LOG_INFO_("\n"); + } /* No child found, deallocate node */ list_remove(nodelist, l); memb_free(&nodememb, l); num_nodes--; + } else if(l->lifetime != UIP_SR_INFINITE_LIFETIME) { + l->lifetime = l->lifetime > seconds ? l->lifetime - seconds : 0; } } } /*---------------------------------------------------------------------------*/ void -rpl_ns_free_all(void) +uip_sr_free_all(void) { - rpl_ns_node_t *l; - rpl_ns_node_t *next; + uip_sr_node_t *l; + uip_sr_node_t *next; for(l = list_head(nodelist); l != NULL; l = next) { next = list_item_next(l); list_remove(nodelist, l); diff --git a/os/net/rpl-lite/rpl-ns.h b/os/net/ipv6/uip-sr.h similarity index 57% rename from os/net/rpl-lite/rpl-ns.h rename to os/net/ipv6/uip-sr.h index 5f6e3d86db49dde6d600f6a49d5f3a8769dd823b..7224cea14daced5ad4041c442d48f226984bf0f2 100644 --- a/os/net/rpl-lite/rpl-ns.h +++ b/os/net/ipv6/uip-sr.h @@ -30,37 +30,75 @@ */ /** - * \addtogroup rpl-lite + * \addtogroup uip * @{ * * \file - * RPL non-storing mode specific functions. Includes support for - * source routing. + * Source routing support * * \author Simon Duquennoy <simon.duquennoy@inria.fr> */ -#ifndef RPL_NS_H -#define RPL_NS_H +#ifndef UIP_SR_H +#define UIP_SR_H /********** Includes **********/ +#include "contiki.h" #include "net/ipv6/uip.h" -#include "net/rpl-lite/rpl.h" + +/********** Configuration **********/ + +/* The number of source routing nodes, i.e. the maximum netwrok size at the root */ +#ifdef UIP_SR_CONF_LINK_NUM + +#define UIP_SR_LINK_NUM UIP_SR_CONF_LINK_NUM + +#else /* UIP_SR_CONF_LINK_NUM */ + +#if ROUTING_CONF_RPL_LITE +#define UIP_SR_LINK_NUM NETSTACK_MAX_ROUTE_ENTRIES +#elif ROUTING_CONF_RPL_CLASSIC + +#include "net/routing/rpl-classic/rpl-conf.h" +#if RPL_WITH_NON_STORING +#define UIP_SR_LINK_NUM NETSTACK_MAX_ROUTE_ENTRIES +#else /* RPL_WITH_NON_STORING */ +#define UIP_SR_LINK_NUM 0 +#endif /* RPL_WITH_NON_STORING */ + +#else + +#define UIP_SR_LINK_NUM 0 + +#endif + +#endif /* UIP_SR_CONF_LINK_NUM */ + +/* Delay between between expiration order and actual node removal */ +#ifdef UIP_SR_CONF_REMOVAL_DELAY +#define UIP_SR_REMOVAL_DELAY UIP_SR_CONF_REMOVAL_DELAY +#else /* UIP_SR_CONF_REMOVAL_DELAY */ +#define UIP_SR_REMOVAL_DELAY 60 +#endif /* UIP_SR_CONF_REMOVAL_DELAY */ + +#define UIP_SR_INFINITE_LIFETIME 0xFFFFFFFF /********** Data Structures **********/ -/* A node in a RPL Non-storing graph, stored at the root and representing +/** \brief A node in a source routing graph, stored at the root and representing * all child-parent relationship. Used to build source routes */ -typedef struct rpl_ns_node { - struct rpl_ns_node *next; +typedef struct uip_sr_node { + struct uip_sr_node *next; uint32_t lifetime; - rpl_dag_t *dag; - /* Store only IPv6 link identifiers as all nodes in the DAG share the same prefix */ + /* Protocol-specific graph structure */ + void *graph; + /* Store only IPv6 link identifiers, the routing protocol will provide + us with the prefix */ unsigned char link_identifier[8]; - struct rpl_ns_node *parent; -} rpl_ns_node_t; + struct uip_sr_node *parent; +} uip_sr_node_t; /********** Public functions **********/ @@ -69,31 +107,33 @@ typedef struct rpl_ns_node { * * \return The number of nodes */ -int rpl_ns_num_nodes(void); +int uip_sr_num_nodes(void); /** * Expires a given child-parent link * + * \param graph The graph the link belongs to * \param child The IPv6 address of the child * \param parent The IPv6 address of the parent */ -void rpl_ns_expire_parent(const uip_ipaddr_t *child, const uip_ipaddr_t *parent); +void uip_sr_expire_parent(void *graph, const uip_ipaddr_t *child, const uip_ipaddr_t *parent); /** * Updates a child-parent link * + * \param graph The graph the link belongs to * \param child The IPv6 address of the child * \param parent The IPv6 address of the parent * \param lifetime The link lifetime in seconds */ -rpl_ns_node_t *rpl_ns_update_node(const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime); +uip_sr_node_t *uip_sr_update_node(void *graph, const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime); /** * Returns the head of the non-storing node list * * \return The head of the list */ -rpl_ns_node_t *rpl_ns_node_head(void); +uip_sr_node_t *uip_sr_node_head(void); /** * Returns the next element of the non-storing node list @@ -101,33 +141,26 @@ rpl_ns_node_t *rpl_ns_node_head(void); * \param item The current element in the list * \return The next element of the list */ -rpl_ns_node_t *rpl_ns_node_next(rpl_ns_node_t *item); +uip_sr_node_t *uip_sr_node_next(uip_sr_node_t *item); /** - * Looks up for a RPL NS node from its IPv6 global address + * Looks up for a source routing node from its IPv6 global address * + * \param graph The graph where to look up for the node * \param addr The target address * \return A pointer to the node */ -rpl_ns_node_t *rpl_ns_get_node(const uip_ipaddr_t *addr); +uip_sr_node_t *uip_sr_get_node(void *graph, const uip_ipaddr_t *addr); /** * Telle whether an address is reachable, i.e. if there exists a path from - * the root to the node in the current RPL NS graph + * the root to the node in the current source routing graph * + * \param graph The graph where to look up for the node * \param addr The target IPv6 global address * \return 1 if the node is reachable, 0 otherwise */ -int rpl_ns_is_addr_reachable(const uip_ipaddr_t *addr); - -/** - * Finds the global address of a given node - * - * \param addr A pointer to the address to be written - * \param node The target node - * \return 1 if success, 0 otherwise -*/ -int rpl_ns_get_node_global_addr(uip_ipaddr_t *addr, rpl_ns_node_t *node); +int uip_sr_is_addr_reachable(void *graph, const uip_ipaddr_t *addr); /** * A function called periodically. Used to age the links (decrease lifetime @@ -135,18 +168,18 @@ int rpl_ns_get_node_global_addr(uip_ipaddr_t *addr, rpl_ns_node_t *node); * * \param seconds The number of seconds elapsted since last call */ -void rpl_ns_periodic(unsigned seconds); +void uip_sr_periodic(unsigned seconds); /** - * Initialize rpl-ns module + * Initialize this module */ -void rpl_ns_init(void); +void uip_sr_init(void); /** * Deallocate all neighbors */ -void rpl_ns_free_all(void); +void uip_sr_free_all(void); /** @} */ -#endif /* RPL_NS_H */ +#endif /* UIP_SR_H */ diff --git a/os/net/ipv6/uip.h b/os/net/ipv6/uip.h index 809f4b4bc6089f7f6b8bb8f9b0d0bf3392649a2b..7751b8fc38d328ddfb4eb8380d4847a4be13e35a 100755 --- a/os/net/ipv6/uip.h +++ b/os/net/ipv6/uip.h @@ -80,6 +80,7 @@ #include "net/ipv6/uipopt.h" +#include "net/ipv6/uipbuf.h" /* For memcmp */ #include <string.h> @@ -499,7 +500,7 @@ typedef union { uint8_t u8[UIP_BUFSIZE]; } uip_buf_t; -CCIF extern uip_buf_t uip_aligned_buf; +extern uip_buf_t uip_aligned_buf; /** Macro to access uip_aligned_buf as an array of bytes */ #define uip_buf (uip_aligned_buf.u8) @@ -619,7 +620,7 @@ struct uip_conn *uip_connect(const uip_ipaddr_t *ripaddr, uint16_t port); * * \hideinitializer */ -CCIF void uip_send(const void *data, int len); +void uip_send(const void *data, int len); /** * The length of any incoming data that is currently available (if available) @@ -883,6 +884,7 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport); */ #define uip_udp_send(len) uip_send((char *)uip_appdata, len) + /** @} */ /* uIP convenience and converting functions. */ @@ -1236,14 +1238,14 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport); * network byte order, use the UIP_HTONS() macro instead. */ #ifndef uip_htons -CCIF uint16_t uip_htons(uint16_t val); +uint16_t uip_htons(uint16_t val); #endif /* uip_htons */ #ifndef uip_ntohs #define uip_ntohs uip_htons #endif #ifndef uip_htonl -CCIF uint32_t uip_htonl(uint32_t val); +uint32_t uip_htonl(uint32_t val); #endif /* uip_htonl */ #ifndef uip_ntohl #define uip_ntohl uip_htonl @@ -1258,7 +1260,7 @@ CCIF uint32_t uip_htonl(uint32_t val); * called. If the application wishes to send data, the application may * use this space to write the data into before calling uip_send(). */ -CCIF extern void *uip_appdata; +extern void *uip_appdata; #if UIP_URGDATA > 0 /* uint8_t *uip_urgdata: @@ -1293,7 +1295,7 @@ extern void *uip_urgdata; * packet. * */ -CCIF extern uint16_t uip_len; +extern uint16_t uip_len; /** * The length of the extension headers @@ -1315,10 +1317,12 @@ extern uint16_t uip_urglen, uip_surglen; #define uip_clear_buf() { \ uip_len = 0; \ uip_ext_len = 0; \ + uipbuf_clear_attr();\ } #else /*NETSTACK_CONF_WITH_IPV6*/ #define uip_clear_buf() { \ uip_len = 0; \ + uipbuf_clear_attr();\ } #endif /*NETSTACK_CONF_WITH_IPV6*/ @@ -1352,7 +1356,6 @@ struct uip_conn { uint8_t timer; /**< The retransmission timer. */ uint8_t nrtx; /**< The number of retransmissions for the last segment sent. */ - uip_tcp_appstate_t appstate; /** The application state. */ }; @@ -1364,10 +1367,10 @@ struct uip_conn { * connection. */ -CCIF extern struct uip_conn *uip_conn; +extern struct uip_conn *uip_conn; #if UIP_TCP /* The array containing all uIP connections. */ -CCIF extern struct uip_conn uip_conns[UIP_TCP_CONNS]; +extern struct uip_conn uip_conns[UIP_TCP_CONNS]; #endif /** @@ -1389,7 +1392,6 @@ struct uip_udp_conn { uint16_t lport; /**< The local port number in network byte order. */ uint16_t rport; /**< The remote port number in network byte order. */ uint8_t ttl; /**< Default time-to-live. */ - /** The application state. */ uip_udp_appstate_t appstate; }; @@ -1520,7 +1522,7 @@ struct uip_eth_hdr { * that are defined in this file. Please read below for more * information. */ -CCIF extern uint8_t uip_flags; +extern uint8_t uip_flags; /* The following flags may be set in the global variable uip_flags before calling the application callback. The UIP_ACKDATA, @@ -1932,17 +1934,17 @@ struct uip_udp_hdr { #if UIP_FIXEDADDR -CCIF extern const uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; +extern const uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; #else /* UIP_FIXEDADDR */ -CCIF extern uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; +extern uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; #endif /* UIP_FIXEDADDR */ -CCIF extern const uip_ipaddr_t uip_broadcast_addr; -CCIF extern const uip_ipaddr_t uip_all_zeroes_addr; +extern const uip_ipaddr_t uip_broadcast_addr; +extern const uip_ipaddr_t uip_all_zeroes_addr; #if UIP_FIXEDETHADDR -CCIF extern const uip_lladdr_t uip_lladdr; +extern const uip_lladdr_t uip_lladdr; #else -CCIF extern uip_lladdr_t uip_lladdr; +extern uip_lladdr_t uip_lladdr; #endif diff --git a/os/net/ipv6/uip6.c b/os/net/ipv6/uip6.c index b0cab3ebd7110ebe68212a3b55961d03e080a6ed..e913a83e13658f67568725101d83e56d9e0dae6b 100644 --- a/os/net/ipv6/uip6.c +++ b/os/net/ipv6/uip6.c @@ -79,15 +79,7 @@ #include "net/ipv6/uip-nd6.h" #include "net/ipv6/uip-ds6.h" #include "net/ipv6/multicast/uip-mcast6.h" - -#if UIP_CONF_IPV6_RPL -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#endif +#include "net/routing/routing.h" #if UIP_ND6_SEND_NS #include "net/ipv6/uip-ds6-nbr.h" @@ -98,6 +90,10 @@ #define LOG_MODULE "IPv6" #define LOG_LEVEL LOG_LEVEL_IPV6 +#if UIP_STATISTICS == 1 +struct uip_stats uip_stat; +#endif /* UIP_STATISTICS == 1 */ + /*---------------------------------------------------------------------------*/ /** * \name Layer 2 variables @@ -157,9 +153,6 @@ uint8_t uip_ext_opt_offset = 0; #define UIP_DESTO_BUF ((struct uip_desto_hdr *)&uip_buf[uip_l2_l3_hdr_len]) #define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) #define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) -#if UIP_CONF_IPV6_RPL -#define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) -#endif /* UIP_CONF_IPV6_RPL */ #define UIP_ICMP6_ERROR_BUF ((struct uip_icmp6_error *)&uip_buf[uip_l2_l3_icmp_hdr_len]) /** @} */ /** @@ -519,6 +512,7 @@ uip_connect(const uip_ipaddr_t *ripaddr, uint16_t rport) void remove_ext_hdr(void) { + int last_uip_ext_len; /* Remove ext header before TCP/UDP processing. */ if(uip_ext_len > 0) { LOG_DBG("Cutting ext-header before processing (extlen: %d, uiplen: %d)\n", @@ -528,15 +522,17 @@ remove_ext_hdr(void) uip_clear_buf(); return; } - memmove(((uint8_t *)UIP_TCP_BUF), (uint8_t *)UIP_TCP_BUF + uip_ext_len, - uip_len - UIP_IPH_LEN - uip_ext_len); + last_uip_ext_len = uip_ext_len; + uip_ext_len = 0; + UIP_IP_BUF->proto = UIP_EXT_BUF->next; + memmove(((uint8_t *)UIP_TCP_BUF), (uint8_t *)UIP_TCP_BUF + last_uip_ext_len, + uip_len - UIP_IPH_LEN - last_uip_ext_len); - uip_len -= uip_ext_len; + uip_len -= last_uip_ext_len; /* Update the IP length. */ UIP_IP_BUF->len[0] = (uip_len - UIP_IPH_LEN) >> 8; UIP_IP_BUF->len[1] = (uip_len - UIP_IPH_LEN) & 0xff; - uip_ext_len = 0; } } /*---------------------------------------------------------------------------*/ @@ -876,13 +872,10 @@ ext_hdr_options_process(void) * Using this fix, the header is ignored, and the next header (if * present) is processed. */ -#if UIP_CONF_IPV6_RPL - LOG_DBG("Processing RPL option\n"); - if(!rpl_ext_header_hbh_update(uip_ext_opt_offset)) { + if(!NETSTACK_ROUTING.ext_header_hbh_update(uip_ext_opt_offset)) { LOG_ERR("RPL Option Error: Dropping Packet\n"); return 1; } -#endif /* UIP_CONF_IPV6_RPL */ uip_ext_opt_offset += (UIP_EXT_HDR_OPT_BUF->len) + 2; return 0; default: @@ -1224,7 +1217,7 @@ uip_process(uint8_t flag) } UIP_IP_BUF->ttl = UIP_IP_BUF->ttl - 1; - LOG_INFO("Forwarding packet to "); + LOG_INFO("Forwarding packet towards "); LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr); LOG_INFO_("\n"); UIP_STAT(++uip_stat.ip.forwarded); @@ -1263,9 +1256,9 @@ uip_process(uint8_t flag) uip_ext_bitmap = 0; #endif /* UIP_CONF_ROUTER */ -#if UIP_IPV6_MULTICAST +#if UIP_IPV6_MULTICAST && UIP_CONF_ROUTER process: -#endif +#endif /* UIP_IPV6_MULTICAST && UIP_CONF_ROUTER */ while(1) { switch(*uip_next_hdr){ @@ -1356,11 +1349,34 @@ uip_process(uint8_t flag) LOG_DBG("Processing Routing header\n"); if(UIP_ROUTING_BUF->seg_left > 0) { -#if UIP_CONF_IPV6_RPL && RPL_WITH_NON_STORING - if(rpl_ext_header_srh_update()) { + if(NETSTACK_ROUTING.ext_header_srh_update()) { + + /* With routing header, the detination address is us and will + * be swapped later to the next hop. Because of this, the MTU + * and TTL were not checked and updated yet. Do this now. */ + + /* Check MTU */ + if(uip_len > UIP_LINK_MTU) { + uip_icmp6_error_output(ICMP6_PACKET_TOO_BIG, 0, UIP_LINK_MTU); + UIP_STAT(++uip_stat.ip.drop); + goto send; + } + /* Check Hop Limit */ + if(UIP_IP_BUF->ttl <= 1) { + uip_icmp6_error_output(ICMP6_TIME_EXCEEDED, + ICMP6_TIME_EXCEED_TRANSIT, 0); + UIP_STAT(++uip_stat.ip.drop); + goto send; + } + UIP_IP_BUF->ttl = UIP_IP_BUF->ttl - 1; + + LOG_INFO("Forwarding packet to next hop "); + LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr); + LOG_INFO_("\n"); + UIP_STAT(++uip_stat.ip.forwarded); + goto send; /* Proceed to forwarding */ } -#endif /* UIP_CONF_IPV6_RPL && RPL_WITH_NON_STORING */ uip_icmp6_error_output(ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, UIP_IPH_LEN + uip_ext_len + 2); UIP_STAT(++uip_stat.ip.drop); LOG_ERR("unrecognized routing type"); @@ -1465,7 +1481,6 @@ uip_process(uint8_t flag) udp_input: remove_ext_hdr(); - UIP_IP_BUF->proto = UIP_PROTO_UDP; LOG_INFO("Receiving UDP packet\n"); @@ -1545,6 +1560,8 @@ uip_process(uint8_t flag) UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); + UIP_IP_BUF->vtc = 0x60; + UIP_IP_BUF->tcflow = 0x00; UIP_IP_BUF->ttl = uip_udp_conn->ttl; UIP_IP_BUF->proto = UIP_PROTO_UDP; @@ -1576,7 +1593,6 @@ uip_process(uint8_t flag) tcp_input: remove_ext_hdr(); - UIP_IP_BUF->proto = UIP_PROTO_TCP; UIP_STAT(++uip_stat.tcp.recv); LOG_INFO("Receiving TCP packet\n"); @@ -2249,6 +2265,9 @@ uip_process(uint8_t flag) UIP_TCP_BUF->srcport = uip_connr->lport; UIP_TCP_BUF->destport = uip_connr->rport; + UIP_IP_BUF->vtc = 0x60; + UIP_IP_BUF->tcflow = 0x00; + uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &uip_connr->ripaddr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); LOG_INFO("Sending TCP packet to "); @@ -2284,8 +2303,6 @@ uip_process(uint8_t flag) #if UIP_UDP ip_send_nolen: #endif - UIP_IP_BUF->vtc = 0x60; - UIP_IP_BUF->tcflow = 0x00; UIP_IP_BUF->flow = 0x00; send: LOG_INFO("Sending packet with length %d (%d)\n", uip_len, diff --git a/os/net/ipv6/uipbuf.c b/os/net/ipv6/uipbuf.c index 074f120664f74ef7c4b601301e8166f71e5ff21e..6ccbb99aa37d18fafb9c255dcff75547fdb49a9f 100644 --- a/os/net/ipv6/uipbuf.c +++ b/os/net/ipv6/uipbuf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, RISE SICS + * Copyright (c) 2017, RISE SICS, Yanzi Networks * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,7 +31,14 @@ */ #include "contiki.h" #include "uip.h" +#include "net/ipv6/uipbuf.h" +#include <string.h> +/*---------------------------------------------------------------------------*/ + +static uint16_t uipbuf_attrs[UIPBUF_ATTR_MAX]; + +/*---------------------------------------------------------------------------*/ /* Get the next header given the buffer - start indicates that this is start of the IPv6 header - needs to be set to 0 when in an ext hdr */ uint8_t* @@ -54,7 +61,7 @@ uipbuf_get_next_header(uint8_t *buffer, uint16_t size, uint8_t *protocol, uint8_ return buffer + ext_len; } } - +/*---------------------------------------------------------------------------*/ /* Get the final header given the buffer - that is assumed to be at start of an IPv6 header */ uint8_t* @@ -69,3 +76,58 @@ uipbuf_get_last_header(uint8_t *buffer, uint16_t size, uint8_t *protocol) } return nbuf; } +/*---------------------------------------------------------------------------*/ +/** + * Common functions for uipbuf (attributes, etc). + * + */ +/*---------------------------------------------------------------------------*/ +uint16_t +uipbuf_get_attr(uint8_t type) +{ + if(type < UIPBUF_ATTR_MAX) { + return uipbuf_attrs[type]; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +int +uipbuf_set_attr(uint8_t type, uint16_t value) +{ + if(type < UIPBUF_ATTR_MAX) { + uipbuf_attrs[type] = value; + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +void +uipbuf_clear_attr(void) +{ + /* set everything to "zero" */ + memset(uipbuf_attrs, 0, sizeof(uipbuf_attrs)); + + /* And initialize anything that should be initialized */ + uipbuf_set_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS, + UIP_MAX_MAC_TRANSMISSIONS_UNDEFINED); +} +/*---------------------------------------------------------------------------*/ +void +uipbuf_set_attr_flag(uint16_t flag) +{ + /* Assume only 16-bits for flags now */ + uipbuf_attrs[UIPBUF_ATTR_FLAGS] |= flag; +} +/*---------------------------------------------------------------------------*/ +void +uipbuf_clr_attr_flag(uint16_t flag) +{ + uipbuf_attrs[UIPBUF_ATTR_FLAGS] &= ~flag; +} +/*---------------------------------------------------------------------------*/ +uint16_t +uipbuf_is_attr_flag(uint16_t flag) +{ + return (uipbuf_attrs[UIPBUF_ATTR_FLAGS] & flag) == flag; +} +/*---------------------------------------------------------------------------*/ diff --git a/os/net/ipv6/uipbuf.h b/os/net/ipv6/uipbuf.h index aaea446d7975b20d56886c9c64ba9d38bc404c79..337ffe17f6509054c0bf411402fd61f3f6e74659 100644 --- a/os/net/ipv6/uipbuf.h +++ b/os/net/ipv6/uipbuf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, RISE SICS + * Copyright (c) 2017, RISE SICS, Yanzi Networks * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,12 +30,112 @@ * */ -#include "contiki.h" +#ifndef UIPBUF_H_ +#define UIPBUF_H_ -/* Get the next header given the buffer - start indicates that this is - start of the IPv6 header - needs to be set to 0 when in an ext hdr */ +#include "contiki.h" +/** + * \brief Get the next IPv6 header. + * \param buffer A pointer to the buffer holding the IPv6 packet + * \param size The size of the data in the buffer + * \param protocol A pointer to a variable where the protocol of the header will be stored + * \param start A flag that indicates if this is expected to be the IPv6 packet header or a later header (Extension header) + * \retval returns address of the starting position of the next header + * + * This function moves to the next header in a IPv6 packet. + */ uint8_t* uipbuf_get_next_header(uint8_t *buffer, uint16_t size, uint8_t *protocol, uint8_t start); -/* Get the final header given the buffer - that is assumed to be at start - of an IPv6 header */ + + +/** + * \brief Get the last IPv6 header. + * \param buffer A pointer to the buffer holding the IPv6 packet + * \param size The size of the data in the buffer + * \param protocol A pointer to a variable where the protocol of the header will be stored + * \retval returns address of the starting position of the next header + * + * This function moves to the last header of the IPv6 packet. + */ uint8_t* uipbuf_get_last_header(uint8_t *buffer, uint16_t size, uint8_t *protocol); + + +/** + * \brief Get the value of the attribute + * \param type The attribute to get the value of + * \retval the value of the attribute + * + * This function gets the value of a specific uipbuf attribute. + */ +uint16_t uipbuf_get_attr(uint8_t type); + + +/** + * \brief Set the value of the attribute + * \param type The attribute to set the value of + * \param value The value to set + * \retval 0 - indicates failure of setting the value + * \retval 1 - indicates success of setting the value + * + * This function sets the value of a specific uipbuf attribute. + */ +int uipbuf_set_attr(uint8_t type, uint16_t value); + +/** + * \brief Set bits in the uipbuf attribute flags. + * \param flag_bits The bits to set in the flag. + * + * This function sets the uipbuf attributes flag of specified bits. + */ +void uipbuf_set_attr_flag(uint16_t flag_bits); + +/** + * \brief Clear bits in the uipbuf attribute flags. + * \param flag_bits The bits to clear in the flag. + * + * This function clears the uipbuf attributes flag of specified bits. + */ +void uipbuf_clr_attr_flag(uint16_t flag_bits); + +/** + * \brief Check if bits in the uipbuf attribute flag are set. + * \param flag_bits The bits to check in the flag. + * + * This function checks if the specified bits are set in the + * uipbuf attributes flag. + */ +uint16_t uipbuf_is_attr_flag(uint16_t flag_bits); + + +/** + * \brief Clear all attributes. + * + * This function clear all attributes in the uipbuf attributes + * including all flags. + */ +void uipbuf_clear_attr(void); + +/** + * \brief The bits defined for uipbuf attributes flag. + * + */ +/* Avoid using NHC compression on the packet (6LoWPAN) */ +#define UIPBUF_ATTR_FLAGS_6LOWPAN_NO_NHC_COMPRESSION 0x01 +/* Avoid using prefix compression on the packet (6LoWPAN) */ +#define UIPBUF_ATTR_FLAGS_6LOWPAN_NO_PREFIX_COMPRESSION 0x02 + +/** + * \brief The attributes defined for uipbuf attributes function. + * + */ +enum { + UIPBUF_ATTR_LLSEC_LEVEL, /**< Control link layer security level. */ + UIPBUF_ATTR_LLSEC_KEY_ID, /**< Control link layer security key ID. */ + UIPBUF_ATTR_INTERFACE_ID, /**< The interface to output packet on */ + UIPBUF_ATTR_PHYSICAL_NETWORK_ID, /**< Physical network ID (mapped to PAN ID)*/ + UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS, /**< MAX transmissions of the packet MAC */ + UIPBUF_ATTR_FLAGS, /**< Flags that can control lower layers. see above. */ + UIPBUF_ATTR_MAX +}; + +#endif /* UIPBUF_H_ */ diff --git a/os/net/ipv6/uiplib.c b/os/net/ipv6/uiplib.c index 4cc9179ebbc22c8e8b466cc1701cfa9cb0cd8b86..afe6de42b5f91d869e3cb1a2283cb172fab88de7 100644 --- a/os/net/ipv6/uiplib.c +++ b/os/net/ipv6/uiplib.c @@ -32,15 +32,27 @@ * */ +/** + * \file + * Various uIP library functions. + * \author + * Nicolas Tsiftes <nvt@sics.se> + * Niclas Finne <nfi@sics.se> + * Joakim Eriksson <joakime@sics.se> + */ #include "net/ipv6/uip.h" #include "net/ipv6/uiplib.h" +#include "net/ipv6/ip64-addr.h" #include <string.h> +#include <stdio.h> -#define DEBUG DEBUG_NONE -#include "net/ipv6/uip-debug.h" +/* Log configuration */ +#include "sys/log.h" +#define LOG_MODULE "uiplib" +#define LOG_LEVEL LOG_LEVEL_NONE -/*-----------------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #if NETSTACK_CONF_WITH_IPV6 int uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *ipaddr) @@ -81,19 +93,19 @@ uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *ipaddr) } else if(c >= 'A' && c <= 'F') { tmp = c - 'A' + 10; } else { - PRINTF("uiplib: illegal char: '%c'\n", c); + LOG_ERR("illegal char: '%c'\n", c); return 0; } value = (value << 4) + (tmp & 0xf); } } if(c != '\0' && c != ']' && c != '/') { - PRINTF("uiplib: too large address\n"); + LOG_ERR("too large address\n"); return 0; } if(len < sizeof(uip_ip6addr_t)) { if(zero < 0) { - PRINTF("uiplib: too short address\n"); + LOG_ERR("too short address\n"); return 0; } memmove(&ipaddr->u8[zero + sizeof(uip_ip6addr_t) - len], @@ -104,7 +116,7 @@ uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *ipaddr) return 1; } #endif /* NETSTACK_CONF_WITH_IPV6 */ -/*-----------------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /* Parse a IPv4-address from a string. Returns the number of characters read * for the address. */ int @@ -138,6 +150,111 @@ uiplib_ip4addrconv(const char *addrstr, uip_ip4addr_t *ipaddr) } while(c != '.' && c != 0 && c != ' '); } - return charsread-1; + return charsread - 1; +} +/*---------------------------------------------------------------------------*/ +void +uiplib_ipaddr_print(const uip_ipaddr_t *addr) +{ + uint16_t a; + unsigned int i; + int f; + + if(addr == NULL) { + printf("(NULL IP addr)"); + return; + } + + if(ip64_addr_is_ipv4_mapped_addr(addr)) { + /* + * Printing IPv4-mapped addresses is done according to RFC 4291 [1] + * + * "An alternative form that is sometimes more + * convenient when dealing with a mixed environment + * of IPv4 and IPv6 nodes is x:x:x:x:x:x:d.d.d.d, + * where the 'x's are the hexadecimal values of the + * six high-order 16-bit pieces of the address, and + * the 'd's are the decimal values of the four + * low-order 8-bit pieces of the address (standard + * IPv4 representation)." + * + * [1] https://tools.ietf.org/html/rfc4291#page-4 + */ + printf("::FFFF:%u.%u.%u.%u", addr->u8[12], addr->u8[13], addr->u8[14], addr->u8[15]); + } else { + for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { + a = (addr->u8[i] << 8) + addr->u8[i + 1]; + if(a == 0 && f >= 0) { + if(f++ == 0) { + printf("::"); + } + } else { + if(f > 0) { + f = -1; + } else if(i > 0) { + printf(":"); + } + printf("%x", a); + } + } + } +} +/*---------------------------------------------------------------------------*/ +int +uiplib_ipaddr_snprint(char *buf, size_t size, const uip_ipaddr_t *addr) +{ + uint16_t a; + unsigned int i; + int f, n; + + if(size == 0) { + return 0; + } + + if(addr == NULL) { + n = snprintf(buf, size - 1, "(NULL IP addr)"); + + } else if(ip64_addr_is_ipv4_mapped_addr(addr)) { + /* + * Printing IPv4-mapped addresses is done according to RFC 4291 [1] + * + * "An alternative form that is sometimes more + * convenient when dealing with a mixed environment + * of IPv4 and IPv6 nodes is x:x:x:x:x:x:d.d.d.d, + * where the 'x's are the hexadecimal values of the + * six high-order 16-bit pieces of the address, and + * the 'd's are the decimal values of the four + * low-order 8-bit pieces of the address (standard + * IPv4 representation)." + * + * [1] https://tools.ietf.org/html/rfc4291#page-4 + */ + n = snprintf(buf, size - 1, "::FFFF:%u.%u.%u.%u", addr->u8[12], + addr->u8[13], addr->u8[14], addr->u8[15]); + } else { + for(n = 0, i = 0, f = 0; i < sizeof(uip_ipaddr_t) && n < size - 1; i += 2) { + a = (addr->u8[i] << 8) + addr->u8[i + 1]; + if(a == 0 && f >= 0) { + if(f++ == 0) { + buf[n++] = ':'; + buf[n++] = ':'; + } + } else { + if(f > 0) { + f = -1; + } else if(i > 0) { + buf[n++] = ':'; + } + n += snprintf(&buf[n], size - n - 1, "%x", a); + } + } + } + + /* + * Make sure the output string is always null-terminated. + */ + buf[MIN(n, size - 1)] = '\0'; + + return n; } -/*-----------------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ diff --git a/os/net/ipv6/uiplib.h b/os/net/ipv6/uiplib.h index aa23435e0ab2289d9b1c10ad84dc2241dd28c0cd..6a122033e89fe391e696f95e30241babc643c729 100644 --- a/os/net/ipv6/uiplib.h +++ b/os/net/ipv6/uiplib.h @@ -73,8 +73,32 @@ #define uiplib_ipaddrconv uiplib_ip4addrconv #endif /* NETSTACK_CONF_WITH_IPV6 */ -CCIF int uiplib_ip4addrconv(const char *addrstr, uip_ip4addr_t *addr); -CCIF int uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *addr); +int uiplib_ip4addrconv(const char *addrstr, uip_ip4addr_t *addr); +int uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *addr); +/** @} */ + +/** + * \addtogroup uiplib + * @{ + */ + +/** + * Print an IP address using printf(). + * + * \param addr A pointer to a uip_ipaddr_t that will be printed with printf(). + */ +void uiplib_ipaddr_print(const uip_ipaddr_t *addr); + +/** + * Write at most size - 1 characters of the IP address to the output string. + * The output is always null-terminated, unless size is 0. + * + * \param buffer A pointer to an output string with at least size bytes. + * \param size The max number of characters to write to the output string. + * \param addr A pointer to a uip_ipaddr_t that will be printed with printf(). + */ +int uiplib_ipaddr_snprint(char *buffer, size_t size, const uip_ipaddr_t *addr); + /** @} */ #endif /* UIPLIB_H_ */ diff --git a/os/net/ipv6/uipopt.h b/os/net/ipv6/uipopt.h index 84b7fd023deadf83900965c31e7510acdab98551..15c79e20a9eaaf879b40f04f6703588652b4e884 100644 --- a/os/net/ipv6/uipopt.h +++ b/os/net/ipv6/uipopt.h @@ -518,6 +518,32 @@ void uip_log(char *msg); #define UIP_DEFAULT_PREFIX_LEN 64 +/** + * The MAC-layer transmissons limit is encapslated in "Traffic Class" field + * + * In Contiki, if the Traffic Class field in the IPv6 header has this bit set, + * the low-order bits are used as the MAC-layer transmissons limit. + */ +#define UIP_TC_MAC_TRANSMISSION_COUNTER_BIT 0x40 + +/** + * The bits in the "Traffic Class" field that describe the MAC transmission limit + */ +#define UIP_TC_MAC_TRANSMISSION_COUNTER_MASK 0x3F + +#ifdef UIP_CONF_TAG_TC_WITH_VARIABLE_RETRANSMISSIONS +#define UIP_TAG_TC_WITH_VARIABLE_RETRANSMISSIONS UIP_CONF_TAG_TC_WITH_VARIABLE_RETRANSMISSIONS +#else +#define UIP_TAG_TC_WITH_VARIABLE_RETRANSMISSIONS 0 +#endif + +/** + * This is the default value of MAC-layer transmissons for uIPv6 + * + * It means that the limit is selected by the MAC protocol instead of uIPv6. + */ +#define UIP_MAX_MAC_TRANSMISSIONS_UNDEFINED 0 + /** @} */ /*------------------------------------------------------------------------------*/ diff --git a/os/net/link-stats.c b/os/net/link-stats.c index 60b107aecd00261bb84c659de140d43a92de60ab..fbb7677daf5ec6404eab7504218060137334e817 100644 --- a/os/net/link-stats.c +++ b/os/net/link-stats.c @@ -64,7 +64,7 @@ /* ETX fixed point divisor. 128 is the value used by RPL (RFC 6551 and RFC 6719) */ #define ETX_DIVISOR LINK_STATS_ETX_DIVISOR /* Number of Tx used to update the ETX EWMA in case of no-ACK */ -#define ETX_NOACK_PENALTY 16 +#define ETX_NOACK_PENALTY 20 /* Initial ETX value */ #define ETX_DEFAULT 2 diff --git a/os/net/mac/ble/ble-l2cap.c b/os/net/mac/ble/ble-l2cap.c new file mode 100644 index 0000000000000000000000000000000000000000..f12fbb369e18c3bb9b1d4943f4698e24093e9a78 --- /dev/null +++ b/os/net/mac/ble/ble-l2cap.c @@ -0,0 +1,590 @@ +/* + * Copyright (c) 2017, Graz University of Technology + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * MAC layer that implements BLE L2CAP credit-based flow control + * channels to support IPv6 over BLE (RFC 7668) + * + * \author + * Michael Spoerk <michael.spoerk@tugraz.at> + */ +/*---------------------------------------------------------------------------*/ + +#include "net/mac/ble/ble-l2cap.h" + +#include "net/packetbuf.h" +#include "net/netstack.h" +#include "lib/memb.h" +#include "lib/list.h" + +#include <string.h> + +#include "../../../dev/ble-hal.h" +/*---------------------------------------------------------------------------*/ +#include "sys/log.h" +#define LOG_MODULE "L2CAP" +#define LOG_LEVEL LOG_LEVEL_MAC +/*---------------------------------------------------------------------------*/ +#define MS_TO_CLOCK_SECONDS(X) ((int)(((double)((X)*CLOCK_SECOND)) / 1000.0)) +/*---------------------------------------------------------------------------*/ +/* BLE controller */ +/* public device address of BLE controller */ +static uint8_t ble_addr[BLE_ADDR_SIZE]; +/*---------------------------------------------------------------------------*/ +/* L2CAP fragmentation buffers and utilities */ +typedef struct { + /* L2CAP Service Data Unit (SDU) (= packet data)*/ + uint8_t sdu[BLE_L2CAP_NODE_MTU]; + /* length of the L2CAP SDU */ + uint16_t sdu_length; + /* index of the first byte not sent yet */ + uint16_t current_index; +} l2cap_buffer_t; +/*---------------------------------------------------------------------------*/ +typedef struct { + uint16_t cid; + uint16_t mtu; + uint16_t mps; + uint16_t credits; +} ble_mac_l2cap_channel_t; +/*---------------------------------------------------------------------------*/ +typedef struct { + ble_mac_l2cap_channel_t channel_own; + ble_mac_l2cap_channel_t channel_peer; + l2cap_buffer_t tx_buffer; + l2cap_buffer_t rx_buffer; + linkaddr_t peer_addr; +} l2cap_channel_t; + +static uint8_t l2cap_channel_count; +static l2cap_channel_t l2cap_channels[L2CAP_CHANNELS]; +static process_event_t l2cap_tx_event; +/*---------------------------------------------------------------------------*/ +static l2cap_channel_t * +get_channel_for_addr(const linkaddr_t *peer_addr) +{ + uint8_t i; + l2cap_channel_t *channel; + for(i = 0; i < l2cap_channel_count; i++) { + channel = &l2cap_channels[i]; + if(linkaddr_cmp(peer_addr, &channel->peer_addr) != 0) { + return channel; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +static l2cap_channel_t * +get_channel_for_cid(uint16_t own_cid) +{ + uint8_t i = own_cid - L2CAP_FLOW_CHANNEL; + if(i >= 0 && i < l2cap_channel_count) { + return &l2cap_channels[own_cid - L2CAP_FLOW_CHANNEL]; + } else { + return NULL; + } +} +/*---------------------------------------------------------------------------*/ +PROCESS(ble_l2cap_tx_process, "BLE L2CAP TX process"); +/*---------------------------------------------------------------------------*/ +static uint8_t +init_adv_data(char *adv_data) +{ + uint8_t adv_data_len = 0; + memset(adv_data, 0x00, BLE_ADV_DATA_LEN); + /* BLE flags */ + adv_data[adv_data_len++] = 2; + adv_data[adv_data_len++] = 0x01; + adv_data[adv_data_len++] = 0x05; /* LE limited (no BR/EDR support) */ + /* TX power level */ + adv_data[adv_data_len++] = 2; + adv_data[adv_data_len++] = 0x0A; + adv_data[adv_data_len++] = 0; /* 0 dBm */ + /* service UUIDs (16-bit identifiers) */ + adv_data[adv_data_len++] = 3; + adv_data[adv_data_len++] = 0x03; + adv_data[adv_data_len++] = 0x20; + adv_data[adv_data_len++] = 0x18; /* only IP support service exposed */ + /* service UUIDs (32-bit identifiers) */ + adv_data[adv_data_len++] = 1; + adv_data[adv_data_len++] = 0x05; /* empty list */ + /* service UUIDs (128-bit identifiers) */ + adv_data[adv_data_len++] = 1; + adv_data[adv_data_len++] = 0x07; /* empty list */ + return adv_data_len; +} +/*---------------------------------------------------------------------------*/ +static uint8_t +init_scan_resp_data(char *scan_resp_data) +{ + uint8_t scan_resp_data_len = 0; + memset(scan_resp_data, 0x00, BLE_SCAN_RESP_DATA_LEN); + /* complete device name */ + scan_resp_data[scan_resp_data_len++] = 1 + strlen(BLE_DEVICE_NAME); + scan_resp_data[scan_resp_data_len++] = 0x09; + memcpy(&scan_resp_data[scan_resp_data_len], + BLE_DEVICE_NAME, strlen(BLE_DEVICE_NAME)); + scan_resp_data_len += strlen(BLE_DEVICE_NAME); + /* slave connection interval range */ + scan_resp_data[scan_resp_data_len++] = 5; + scan_resp_data[scan_resp_data_len++] = 0x12; + scan_resp_data[scan_resp_data_len++] = (BLE_SLAVE_CONN_INTERVAL_MIN & 0xFF); + scan_resp_data[scan_resp_data_len++] = ((BLE_SLAVE_CONN_INTERVAL_MIN >> 8) & 0xFF); + scan_resp_data[scan_resp_data_len++] = (BLE_SLAVE_CONN_INTERVAL_MAX & 0xFF); + scan_resp_data[scan_resp_data_len++] = ((BLE_SLAVE_CONN_INTERVAL_MAX >> 8) & 0xFF); + + return scan_resp_data_len; +} +/*---------------------------------------------------------------------------*/ +void +input_l2cap_conn_req(uint8_t *data) +{ + uint8_t identifier = data[0]; + uint16_t len; + uint16_t le_psm; + uint8_t resp_data[18]; + l2cap_channel_t *channel; + + memcpy(&len, &data[1], 2); + + if(len != 10) { + LOG_WARN("l2cap_conn_req: invalid len: %d\n", len); + return; + } + + /* create a new L2CAP connection because of this request */ + if(l2cap_channel_count >= L2CAP_CHANNELS) { + LOG_WARN("l2cap_conn_req: maximum supported L2CAP channels reached\n"); + return; + } + + channel = &l2cap_channels[l2cap_channel_count]; + /* parse L2CAP connection data */ + memcpy(&le_psm, &data[3], 2); + memset(&channel->channel_peer, 0x00, sizeof(ble_mac_l2cap_channel_t)); + memcpy(&channel->channel_peer.cid, &data[5], 2); + memcpy(&channel->channel_peer.mtu, &data[7], 2); + memcpy(&channel->channel_peer.mps, &data[9], 2); + memcpy(&channel->channel_peer.credits, &data[11], 2); + linkaddr_copy(&channel->peer_addr, packetbuf_addr(PACKETBUF_ADDR_SENDER)); + + LOG_INFO("recv CONN_REQ (MTU: %4d, MPS: %4d, credits: %4d)\n", + channel->channel_peer.mtu, channel->channel_peer.mps, channel->channel_peer.credits); + + l2cap_channel_count++; + + /* create L2CAP connection response */ + /* length */ + resp_data[0] = 0x0E; + resp_data[1] = 0x00; + /* channel ID */ + resp_data[2] = 0x05; + resp_data[3] = 0x00; + /* code */ + resp_data[4] = L2CAP_CODE_CONN_RSP; + /* identifier */ + resp_data[5] = identifier; + /* cmd length */ + resp_data[6] = 0x0A; + resp_data[7] = 0x00; + /* node channel information */ + memcpy(&resp_data[8], &channel->channel_own.cid, 2); + memcpy(&resp_data[10], &channel->channel_own.mtu, 2); + memcpy(&resp_data[12], &channel->channel_own.mps, 2); + memcpy(&resp_data[14], &channel->channel_own.credits, 2); + /* result */ + memset(&resp_data[16], 0x00, 2); + + packetbuf_copyfrom((void *)resp_data, 18); + packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr); + packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &channel->peer_addr); + NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ + uint8_t i; + l2cap_tx_event = process_alloc_event(); + LOG_DBG("init()\n"); + /* initialize the L2CAP connection parameter */ + for(i = 0; i < L2CAP_CHANNELS; i++) { + l2cap_channels[i].channel_own.cid = L2CAP_FLOW_CHANNEL + i; + l2cap_channels[i].channel_own.credits = L2CAP_CREDIT_NEW; + l2cap_channels[i].channel_own.mps = (BLE_L2CAP_NODE_FRAG_LEN - L2CAP_SUBSEQ_HEADER_SIZE); + l2cap_channels[i].channel_own.mtu = BLE_L2CAP_NODE_MTU; + } + + /* Initialize the BLE controller */ + NETSTACK_RADIO.init(); + NETSTACK_RADIO.get_object(RADIO_CONST_BLE_BD_ADDR, &ble_addr, BLE_ADDR_SIZE); + + uint8_t adv_data_len, scan_resp_data_len; + char adv_data[BLE_ADV_DATA_LEN]; + char scan_resp_data[BLE_SCAN_RESP_DATA_LEN]; + /* set the advertisement parameter */ + NETSTACK_RADIO.set_value(RADIO_PARAM_BLE_ADV_INTERVAL, BLE_ADV_INTERVAL); + NETSTACK_RADIO.set_value(RADIO_PARAM_BLE_ADV_TYPE, BLE_ADV_DIR_IND_LDC); + NETSTACK_RADIO.set_value(RADIO_PARAM_BLE_ADV_OWN_ADDR_TYPE, BLE_ADDR_TYPE_PUBLIC); + NETSTACK_RADIO.set_value(RADIO_PARAM_BLE_ADV_CHANNEL_MAP, 0x01); + + adv_data_len = init_adv_data(adv_data); + scan_resp_data_len = init_scan_resp_data(scan_resp_data); + + /* set advertisement payload & scan response */ + NETSTACK_RADIO.set_object(RADIO_PARAM_BLE_ADV_PAYLOAD, adv_data, adv_data_len); + NETSTACK_RADIO.set_object(RADIO_PARAM_BLE_ADV_SCAN_RESPONSE, scan_resp_data, scan_resp_data_len); + + /* enable advertisement */ + NETSTACK_RADIO.set_value(RADIO_PARAM_BLE_ADV_ENABLE, 1); + + NETSTACK_MAC.on(); +} +/*---------------------------------------------------------------------------*/ +static uint16_t +check_own_l2cap_credits(l2cap_channel_t *channel) +{ + uint16_t credits_new = 0; + uint16_t credits_current; + + credits_current = channel->channel_own.credits; + if(credits_current < L2CAP_CREDIT_THRESHOLD) { + credits_new = L2CAP_CREDIT_NEW; + } + LOG_DBG("check for new credits: current credits: %2d, new credits: %2d\n", credits_current, credits_new); + return credits_new; +} +/*---------------------------------------------------------------------------*/ +static void +send_l2cap_credit(l2cap_channel_t *channel, uint16_t credits) +{ + uint8_t len = 4; + uint8_t data[12]; + /* create L2CAP credit */ + /* length */ + data[0] = len + 4; + data[1] = 0x00; + /* channel ID */ + data[2] = 0x05; + data[3] = 0x00; + /* code */ + data[4] = L2CAP_CODE_CREDIT; + /* identifier */ + data[5] = 0xFF; + /* cmd length */ + data[6] = len; + data[7] = 0x00; + + memcpy(&data[8], &channel->channel_own.cid, 2); + data[10] = credits & 0xFF; + data[11] = credits >> 8; + + channel->channel_own.credits += credits; + + packetbuf_copyfrom((void *)data, len + 8); + packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr); + packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &channel->peer_addr); + NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); +} +/*---------------------------------------------------------------------------*/ +static void +send(mac_callback_t sent_callback, void *ptr) +{ + uint8_t i; + l2cap_channel_t *channel; + uint16_t data_len = packetbuf_datalen(); + LOG_DBG("send %d\n", data_len); + + /* packet is too long */ + if(data_len > BLE_L2CAP_NODE_MTU) { + LOG_WARN("send message is too long\n"); + mac_call_sent_callback(sent_callback, ptr, MAC_TX_ERR, 0); + return; + } + + for(i = 0; i < l2cap_channel_count; i++) { + channel = &l2cap_channels[i]; + if((linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_null) != 0) + || (linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &channel->peer_addr) != 0)) { + if(channel->tx_buffer.sdu_length > 0) { + LOG_WARN("send() another L2CAP message active (trying to send %4d bytes)\n", data_len); + mac_call_sent_callback(sent_callback, ptr, MAC_TX_COLLISION, 0); + return; + } + LOG_DBG("send() adding to L2CAP CID: %2d\n", channel->channel_own.cid); + channel->tx_buffer.sdu_length = data_len; + if(channel->tx_buffer.sdu_length > 0) { + memcpy(&channel->tx_buffer.sdu, packetbuf_dataptr(), data_len); + mac_call_sent_callback(sent_callback, ptr, MAC_TX_DEFERRED, 1); + process_post(&ble_l2cap_tx_process, l2cap_tx_event, (void *)channel); + } + } + } +} +/*---------------------------------------------------------------------------*/ +void +input_l2cap_connection_udate_resp(uint8_t *data) +{ + uint16_t len; + uint16_t result; + + memcpy(&len, &data[1], 2); + + if(len != 2) { + LOG_WARN("input_l2cap_connection_update_resp: invalid len: %d\n", len); + return; + } + + memcpy(&result, &data[3], 2); + if(result != 0x0000) { + LOG_WARN("input_l2cap_connection_update_resp: result: 0x%04X\n", result); + return; + } +} +/*---------------------------------------------------------------------------*/ +void +input_l2cap_credit(uint8_t *data) +{ + uint16_t len; + uint16_t cid; + uint16_t credits; + l2cap_channel_t *channel = get_channel_for_addr(packetbuf_addr(PACKETBUF_ADDR_SENDER)); + +/* uint8_t identifier = data[0]; */ + memcpy(&len, &data[1], 2); + + if(len != 4) { + LOG_WARN("process_l2cap_credit: invalid len: %d\n", len); + return; + } + + /* parse L2CAP credit data */ + memcpy(&cid, &data[3], 2); + memcpy(&credits, &data[5], 2); + + channel->channel_peer.credits += credits; +} +/*---------------------------------------------------------------------------*/ +static void +input_l2cap_frame_signal_channel(uint8_t *data, uint8_t data_len) +{ + if(data[4] == L2CAP_CODE_CREDIT) { + input_l2cap_credit(&data[5]); + } else if(data[4] == L2CAP_CODE_CONN_REQ) { + input_l2cap_conn_req(&data[5]); + } else if(data[4] == L2CAP_CODE_CONN_UPDATE_RSP) { + input_l2cap_connection_udate_resp(&data[5]); + } else { + LOG_WARN("l2cap_frame_signal_channel: unknown signal channel code: %d\n", data[4]); + } +} +/*---------------------------------------------------------------------------*/ +static void +input_l2cap_frame_flow_channel(l2cap_channel_t *channel, uint8_t *data, uint16_t data_len) +{ + uint16_t frame_len; + uint16_t payload_len; + + if(data_len < 4) { + LOG_WARN("l2cap_frame: illegal L2CAP frame data_len: %d\n", data_len); + /* a L2CAP frame has a minimum length of 4 */ + return; + } + + if(channel->rx_buffer.sdu_length == 0) { + /* handle first fragment */ + memcpy(&frame_len, &data[0], 2); + memcpy(&channel->rx_buffer.sdu_length, &data[4], 2); + payload_len = frame_len - 2; + + memcpy(channel->rx_buffer.sdu, &data[6], payload_len); + channel->rx_buffer.current_index = payload_len; + } else { + /* subsequent fragment */ + memcpy(&frame_len, &data[0], 2); + payload_len = frame_len; + + memcpy(&channel->rx_buffer.sdu[channel->rx_buffer.current_index], &data[4], payload_len); + channel->rx_buffer.current_index += payload_len; + } + + if((channel->rx_buffer.sdu_length > 0) && + (channel->rx_buffer.sdu_length == channel->rx_buffer.current_index)) { + /* do not use packetbuf_copyfrom here because the packetbuf_attr + * must not be cleared */ + memcpy(packetbuf_dataptr(), channel->rx_buffer.sdu, channel->rx_buffer.sdu_length); + packetbuf_set_datalen(channel->rx_buffer.sdu_length); + NETSTACK_NETWORK.input(); + + /* reset counters */ + channel->rx_buffer.sdu_length = 0; + channel->rx_buffer.current_index = 0; + } +} +/*---------------------------------------------------------------------------*/ +static void +input(void) +{ + uint8_t *data = (uint8_t *)packetbuf_dataptr(); + uint16_t len = packetbuf_datalen(); + uint8_t frame_type = packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE); + uint16_t channel_id; + l2cap_channel_t *channel; + uint16_t credits; + + if(frame_type == FRAME_BLE_RX_EVENT) { + memcpy(&channel_id, &data[2], 2); + channel = get_channel_for_cid(channel_id); + LOG_DBG("input %d bytes\n", len); + if(channel_id == L2CAP_SIGNAL_CHANNEL) { + input_l2cap_frame_signal_channel(data, len); + } else if(channel == NULL) { + LOG_WARN("input (RX_EVENT): no channel found for CID: %d\n", channel_id); + return; + } else { + input_l2cap_frame_flow_channel(channel, data, len); + channel->channel_own.credits--; + credits = check_own_l2cap_credits(channel); + if(credits > 0) { + send_l2cap_credit(channel, credits); + } + } + } + /* check if there are still fragments left to be transmitted */ + if(frame_type == FRAME_BLE_TX_EVENT) { + channel = get_channel_for_addr(packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); + if(channel == NULL) { + LOG_WARN("input (TX_EVENT): no channel found for CID: %d\n", channel_id); + } else if(channel->tx_buffer.sdu_length > 0) { + process_post(&ble_l2cap_tx_process, l2cap_tx_event, (void *)channel); + } + } +} +/*---------------------------------------------------------------------------*/ +static int +on(void) +{ + LOG_DBG("on()\n"); + process_start(&ble_l2cap_tx_process, NULL); + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +off(void) +{ + LOG_DBG("off()\n"); + process_exit(&ble_l2cap_tx_process); + return 0; +} +/*---------------------------------------------------------------------------*/ +const struct mac_driver ble_l2cap_driver = { + "ble-l2cap", + init, + send, + input, + on, + off, + NULL, +}; +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(ble_l2cap_tx_process, ev, data) +{ + uint16_t data_len; + uint16_t frame_len; + uint16_t num_buffer; + l2cap_channel_t *channel = (l2cap_channel_t *)data; + uint8_t first_fragment; + uint16_t used_mps; + uint16_t credits; + + PROCESS_BEGIN(); + LOG_DBG("starting ble_mac_tx_process\n"); + + while(1) { + PROCESS_YIELD_UNTIL(ev == l2cap_tx_event); + if(channel != NULL) { + NETSTACK_RADIO.get_value(RADIO_CONST_BLE_BUFFER_AMOUNT, (radio_value_t *)&num_buffer); + first_fragment = (channel->tx_buffer.current_index == 0); + used_mps = MIN(channel->channel_own.mps, channel->channel_peer.mps); + credits = channel->channel_peer.credits; + + LOG_DBG("process: sending - first: %d, used_mps: %3d, num_buffers: %2d, credits: %2d\n", + first_fragment, used_mps, num_buffer, credits); + if((channel->tx_buffer.sdu_length > 0) && (num_buffer > 0) && (credits > 0)) { + packetbuf_clear(); + if(first_fragment) { + packetbuf_hdralloc(L2CAP_FIRST_HEADER_SIZE); + used_mps -= L2CAP_FIRST_HEADER_SIZE; + data_len = MIN(channel->tx_buffer.sdu_length, used_mps); + frame_len = data_len + 2; + + /* set L2CAP header fields */ + memcpy(packetbuf_hdrptr(), &frame_len, 2); /* fragment size */ + memcpy(packetbuf_hdrptr() + 2, &channel->channel_peer.cid, 2); /* L2CAP channel id*/ + memcpy(packetbuf_hdrptr() + 4, &channel->tx_buffer.sdu_length, 2); /* overall packet size */ + } else { + packetbuf_hdralloc(L2CAP_SUBSEQ_HEADER_SIZE); + used_mps -= L2CAP_SUBSEQ_HEADER_SIZE; + data_len = MIN((channel->tx_buffer.sdu_length - channel->tx_buffer.current_index), used_mps); + frame_len = data_len; + + /* set L2CAP header fields */ + memcpy(packetbuf_hdrptr(), &frame_len, 2); /* fragment size */ + memcpy(packetbuf_hdrptr() + 2, &channel->channel_peer.cid, 2); /* L2CAP channel id*/ + } + + /* copy payload */ + memcpy(packetbuf_dataptr(), + &channel->tx_buffer.sdu[channel->tx_buffer.current_index], + data_len); + packetbuf_set_datalen(data_len); + channel->tx_buffer.current_index += data_len; + + /* send the fragment */ + packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &channel->peer_addr); + packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr); + NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); + channel->channel_peer.credits--; + + /* reset the L2CAP TX buffer if packet is finished */ + if(channel->tx_buffer.current_index == channel->tx_buffer.sdu_length) { + channel->tx_buffer.current_index = 0; + channel->tx_buffer.sdu_length = 0; + } + } + } else { + LOG_WARN("process. channel is NULL\n"); + } + } + + PROCESS_END(); + LOG_DBG("stopped ble_mac_tx_process\n"); +} diff --git a/os/net/mac/ble/ble-l2cap.h b/os/net/mac/ble/ble-l2cap.h new file mode 100644 index 0000000000000000000000000000000000000000..73dfa18a5b765eb0655eaff4c8d35534829e99af --- /dev/null +++ b/os/net/mac/ble/ble-l2cap.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2017, Graz University of Technology + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * MAC layer that implements BLE L2CAP credit-based flow control + * channels to support IPv6 over BLE (RFC 7668) + * + * \author + * Michael Spoerk <michael.spoerk@tugraz.at> + */ +/*---------------------------------------------------------------------------*/ +#ifndef BLE_L2CAP_H_ +#define BLE_L2CAP_H_ + +#include "contiki.h" +#include "net/mac/mac.h" +#include "dev/radio.h" +/*---------------------------------------------------------------------------*/ +/* device name used for BLE advertisement */ +#ifdef BLE_CONF_DEVICE_NAME +#define BLE_DEVICE_NAME BLE_CONF_DEVICE_NAME +#else +#define BLE_DEVICE_NAME "BLE device name" +#endif + +/* BLE advertisement in milliseconds */ +#ifdef BLE_CONF_ADV_INTERVAL +#define BLE_ADV_INTERVAL BLE_CONF_ADV_INTERVAL +#else +#define BLE_ADV_INTERVAL 50 +#endif + +#define BLE_SLAVE_CONN_INTERVAL_MIN 0x0150 +#define BLE_SLAVE_CONN_INTERVAL_MAX 0x01F0 +#define L2CAP_SIGNAL_CHANNEL 0x0005 +#define L2CAP_FLOW_CHANNEL 0x0041 +#define L2CAP_CODE_CONN_UPDATE_REQ 0x12 +#define L2CAP_CODE_CONN_UPDATE_RSP 0x13 +#define L2CAP_CODE_CONN_REQ 0x14 +#define L2CAP_CODE_CONN_RSP 0x15 +#define L2CAP_CODE_CREDIT 0x16 +#define L2CAP_IPSP_PSM 0x0023 + +/* the maximum MTU size of the L2CAP channel */ +#ifdef BLE_L2CAP_CONF_NODE_MTU +#define BLE_L2CAP_NODE_MTU BLE_L2CAP_CONF_NODE_MTU +#else +#define BLE_L2CAP_NODE_MTU 1280 +#endif + +/* the max. supported L2CAP fragment length */ +#ifdef BLE_L2CAP_CONF_NODE_FRAG_LEN +#define BLE_L2CAP_NODE_FRAG_LEN BLE_L2CAP_CONF_NODE_FRAG_LEN +#else +#ifdef BLE_MODE_CONF_CONN_MAX_PACKET_SIZE +#define BLE_L2CAP_NODE_FRAG_LEN BLE_MODE_CONF_CONN_MAX_PACKET_SIZE +#else +#define BLE_L2CAP_NODE_FRAG_LEN 256 +#endif +#endif + +#define L2CAP_CREDIT_NEW (BLE_L2CAP_NODE_MTU / BLE_L2CAP_NODE_FRAG_LEN) +#define L2CAP_CREDIT_THRESHOLD 2 + +#define L2CAP_INIT_INTERVAL (2 * CLOCK_SECOND) + +/* BLE connection interval in milliseconds */ +#ifdef BLE_CONF_CONNECTION_INTERVAL +#define CONNECTION_INTERVAL_MS BLE_CONF_CONNECTION_INTERVAL +#else +#define CONNECTION_INTERVAL_MS 125 +#endif + +/* BLE slave latency */ +#ifdef BLE_CONF_CONNECTION_SLAVE_LATENCY +#define CONNECTION_SLAVE_LATENCY BLE_CONF_CONNECTION_SLAVE_LATENCY +#else +#define CONNECTION_SLAVE_LATENCY 0 +#endif + +/* BLE supervision timeout */ +#define CONNECTION_TIMEOUT 42 + +#define L2CAP_FIRST_HEADER_SIZE 6 +#define L2CAP_SUBSEQ_HEADER_SIZE 4 + +#if UIP_CONF_ROUTER +#ifdef BLE_MODE_CONF_MAX_CONNECTIONS +#define L2CAP_CHANNELS BLE_MODE_CONF_MAX_CONNECTIONS +#else +#define L2CAP_CHANNELS 1 +#endif +#else +#define L2CAP_CHANNELS 1 +#endif + +extern const struct mac_driver ble_l2cap_driver; + +#endif /* BLE_L2CAP_H_ */ diff --git a/os/net/mac/csma/csma-output.c b/os/net/mac/csma/csma-output.c index 167d4374ca1063a594588cf84c8efdca6e442d88..9c88d569d4c45178e9312eb3f367f26e1a5b4e73 100644 --- a/os/net/mac/csma/csma-output.c +++ b/os/net/mac/csma/csma-output.c @@ -50,10 +50,10 @@ #include "lib/list.h" #include "lib/memb.h" -#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 +#if CONTIKI_TARGET_COOJA #include "lib/simEnvChange.h" #include "sys/cooja_mt.h" -#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */ +#endif /* CONTIKI_TARGET_COOJA */ /* Log configuration */ #include "sys/log.h" @@ -66,14 +66,14 @@ #ifdef CSMA_CONF_MIN_BE #define CSMA_MIN_BE CSMA_CONF_MIN_BE #else -#define CSMA_MIN_BE 0 +#define CSMA_MIN_BE 3 #endif /* macMaxBE: Maximum backoff exponent. Range 3--8 */ #ifdef CSMA_CONF_MAX_BE #define CSMA_MAX_BE CSMA_CONF_MAX_BE #else -#define CSMA_MAX_BE 4 +#define CSMA_MAX_BE 5 #endif /* macMaxCSMABackoffs: Maximum number of backoffs in case of channel busy/collision. Range 0--5 */ @@ -85,9 +85,9 @@ /* macMaxFrameRetries: Maximum number of re-transmissions attampts. Range 0--7 */ #ifdef CSMA_CONF_MAX_FRAME_RETRIES -#define CSMA_MAX_MAX_FRAME_RETRIES CSMA_CONF_MAX_FRAME_RETRIES +#define CSMA_MAX_FRAME_RETRIES CSMA_CONF_MAX_FRAME_RETRIES #else -#define CSMA_MAX_MAX_FRAME_RETRIES 7 +#define CSMA_MAX_FRAME_RETRIES 7 #endif /* Packet metadata */ @@ -154,9 +154,15 @@ neighbor_queue_from_addr(const linkaddr_t *addr) static clock_time_t backoff_period(void) { +#if CONTIKI_TARGET_COOJA + /* Increase normal value by 20 to compensate for the coarse-grained + radio medium with Cooja motes */ + return MAX(20 * CLOCK_SECOND / 3125, 1); +#else /* CONTIKI_TARGET_COOJA */ /* Use the default in IEEE 802.15.4: aUnitBackoffPeriod which is * 20 symbols i.e. 320 usec. That is, 1/3125 second. */ return MAX(CLOCK_SECOND / 3125, 1); +#endif /* CONTIKI_TARGET_COOJA */ } /*---------------------------------------------------------------------------*/ static int @@ -201,10 +207,10 @@ send_one_packet(void *ptr) wt = RTIMER_NOW(); watchdog_periodic(); while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + CSMA_ACK_WAIT_TIME)) { -#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 +#if CONTIKI_TARGET_COOJA simProcessRunValue = 1; cooja_mt_yield(); -#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */ +#endif /* CONTIKI_TARGET_COOJA */ } ret = MAC_TX_NOACK; @@ -219,10 +225,10 @@ send_one_packet(void *ptr) watchdog_periodic(); while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + CSMA_AFTER_ACK_DETECTED_WAIT_TIME)) { -#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 +#if CONTIKI_TARGET_COOJA simProcessRunValue = 1; cooja_mt_yield(); -#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */ +#endif /* CONTIKI_TARGET_COOJA */ } } @@ -281,7 +287,7 @@ schedule_transmission(struct neighbor_queue *n) clock_time_t delay; int backoff_exponent; /* BE in IEEE 802.15.4 */ - backoff_exponent = MIN(n->collisions, CSMA_MAX_BE); + backoff_exponent = MIN(n->collisions + CSMA_MIN_BE, CSMA_MAX_BE); /* Compute max delay as per IEEE 802.15.4: 2^BE-1 backoff periods */ delay = ((1 << backoff_exponent) - 1) * backoff_period(); @@ -310,7 +316,7 @@ free_packet(struct neighbor_queue *n, struct packet_queue *p, int status) if(list_head(n->packet_queue) != NULL) { /* There is a next packet. We reset current tx information */ n->transmissions = 0; - n->collisions = CSMA_MIN_BE; + n->collisions = 0; /* Schedule next transmissions */ schedule_transmission(n); } else { @@ -365,7 +371,7 @@ collision(struct packet_queue *q, struct neighbor_queue *n, n->collisions += num_transmissions; if(n->collisions > CSMA_MAX_BACKOFF) { - n->collisions = CSMA_MIN_BE; + n->collisions = 0; /* Increment to indicate a next retry */ n->transmissions++; } @@ -384,7 +390,7 @@ noack(struct packet_queue *q, struct neighbor_queue *n, int num_transmissions) metadata = (struct qbuf_metadata *)q->ptr; - n->collisions = CSMA_MIN_BE; + n->collisions = 0; n->transmissions += num_transmissions; if(n->transmissions >= metadata->max_transmissions) { @@ -397,7 +403,7 @@ noack(struct packet_queue *q, struct neighbor_queue *n, int num_transmissions) static void tx_ok(struct packet_queue *q, struct neighbor_queue *n, int num_transmissions) { - n->collisions = CSMA_MIN_BE; + n->collisions = 0; n->transmissions += num_transmissions; tx_done(MAC_TX_OK, q, n); } @@ -487,7 +493,7 @@ csma_output_packet(mac_callback_t sent, void *ptr) /* Init neighbor entry */ linkaddr_copy(&n->addr, addr); n->transmissions = 0; - n->collisions = CSMA_MIN_BE; + n->collisions = 0; /* Init packet queue for this neighbor */ LIST_STRUCT_INIT(n, packet_queue); /* Add neighbor to the neighbor list */ @@ -506,14 +512,19 @@ csma_output_packet(mac_callback_t sent, void *ptr) if(q->buf != NULL) { struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr; /* Neighbor and packet successfully allocated */ - metadata->max_transmissions = CSMA_MAX_MAX_FRAME_RETRIES + 1; + metadata->max_transmissions = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS); + if(metadata->max_transmissions == 0) { + /* If not set by the application, use the default CSMA value */ + metadata->max_transmissions = CSMA_MAX_FRAME_RETRIES + 1; + } metadata->sent = sent; metadata->cptr = ptr; list_add(n->packet_queue, q); LOG_INFO("sending to "); LOG_INFO_LLADDR(addr); - LOG_INFO_(", seqno %u, queue length %d, free packets %d\n", + LOG_INFO_(", len %u, seqno %u, queue length %d, free packets %d\n", + packetbuf_datalen(), packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO), list_length(n->packet_queue), memb_numfree(&packet_memb)); /* If q is the first packet in the neighbor's queue, send asap */ diff --git a/os/net/mac/csma/csma.c b/os/net/mac/csma/csma.c index aa7a98a3d9af257a580e610f2e8cb8aa1112a133..7259e35c8e80becfed2a4f30e3a2a0e326aea4d2 100644 --- a/os/net/mac/csma/csma.c +++ b/os/net/mac/csma/csma.c @@ -108,9 +108,9 @@ input_packet(void) } #endif /* CSMA_SEND_SOFT_ACK */ if(!duplicate) { - LOG_WARN("received packet from "); - LOG_WARN_LLADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); - LOG_WARN_(", seqno %u, len %u\n", packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO), packetbuf_datalen()); + LOG_INFO("received packet from "); + LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); + LOG_INFO_(", seqno %u, len %u\n", packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO), packetbuf_datalen()); NETSTACK_NETWORK.input(); } } diff --git a/os/net/mac/framer/frame802154e-ie.h b/os/net/mac/framer/frame802154e-ie.h index eac9045f3e3bc84393f5f07cea6e5bc21732ce80..2df163d7dd6e0802bc246d52795fb39f51b45c0f 100644 --- a/os/net/mac/framer/frame802154e-ie.h +++ b/os/net/mac/framer/frame802154e-ie.h @@ -41,9 +41,13 @@ #define FRAME_802154E_H #include "contiki.h" -/* We need definitions from tsch-private.h for TSCH-specific information elements */ -#include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-private.h" +#include "net/mac/mac.h" +#include "net/linkaddr.h" +/* We need definitions from tsch.h for TSCH-specific information elements */ +#include "net/mac/tsch/tsch-conf.h" +#include "net/mac/tsch/tsch-const.h" +#include "net/mac/tsch/tsch-types.h" +#include "net/mac/tsch/tsch-asn.h" #define FRAME802154E_IE_MAX_LINKS 4 diff --git a/os/net/mac/framer/nullframer.c b/os/net/mac/framer/nullframer.c index 3df8f6ea161e145fb1e3b6471e0d6d1553a55191..019ed2209eda93e1cf2f9fc2ad321149f020affe 100644 --- a/os/net/mac/framer/nullframer.c +++ b/os/net/mac/framer/nullframer.c @@ -36,7 +36,27 @@ * Joakim Eriksson <joakime@sics.se> */ #include "net/mac/framer/framer.h" +#include "net/packetbuf.h" +#ifdef NULLFRAMER_CONF_PARSE_802154 +#define NULLFRAMER_PARSE_802154 NULLFRAMER_CONF_PARSE_802154 +#else +/* defaults to parsing of the 802154 header as that is used for Slip-Radio */ +#define NULLFRAMER_PARSE_802154 1 +#endif + +/*---------------------------------------------------------------------------*/ +static int +is_broadcast_addr(uint8_t mode, uint8_t *addr) +{ + int i = mode == FRAME802154_SHORTADDRMODE ? 2 : 8; + while(i-- > 0) { + if(addr[i] != 0xff) { + return 0; + } + } + return 1; +} /*---------------------------------------------------------------------------*/ static int hdr_length(void) @@ -55,6 +75,21 @@ create(void) static int parse(void) { +#if NULLFRAMER_PARSE_802154 + frame802154_t frame; + int len; + len = packetbuf_datalen(); + if(frame802154_parse(packetbuf_dataptr(), len, &frame)) { + if(frame.fcf.dest_addr_mode) { + if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) { + packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (linkaddr_t *)&frame.dest_addr); + } + } + packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr); + packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq); + return 0; + } +#endif return 0; } /*---------------------------------------------------------------------------*/ diff --git a/os/net/mac/tsch/Makefile.tsch b/os/net/mac/tsch/Makefile.tsch deleted file mode 100644 index e19ff8b1334f5346572a734a5c206cf7e1f3a04e..0000000000000000000000000000000000000000 --- a/os/net/mac/tsch/Makefile.tsch +++ /dev/null @@ -1 +0,0 @@ -CONTIKI_SOURCEFILES += tsch.c tsch-slot-operation.c tsch-queue.c tsch-packet.c tsch-schedule.c tsch-log.c tsch-rpl.c tsch-adaptive-timesync.c diff --git a/os/net/mac/tsch/sixtop/sixp-nbr.c b/os/net/mac/tsch/sixtop/sixp-nbr.c index 8b5d979de658788b5db97f8f78db88aafc654783..7ab0bea90baa09171ef66eae3138c195472b1fbb 100644 --- a/os/net/mac/tsch/sixtop/sixp-nbr.c +++ b/os/net/mac/tsch/sixtop/sixp-nbr.c @@ -61,7 +61,6 @@ typedef struct sixp_nbr { struct sixp_nbr *next; linkaddr_t addr; uint8_t next_seqno; - uint8_t gen; } sixp_nbr_t; NBR_TABLE(sixp_nbr_t, sixp_nbrs); @@ -105,7 +104,6 @@ sixp_nbr_alloc(const linkaddr_t *addr) linkaddr_copy(&nbr->addr, addr); nbr->next_seqno = SIXP_INITIAL_SEQUENCE_NUMBER; - nbr->gen = 0; return nbr; } @@ -119,48 +117,39 @@ sixp_nbr_free(sixp_nbr_t *nbr) } } /*---------------------------------------------------------------------------*/ -int16_t -sixp_nbr_get_gen(sixp_nbr_t *nbr) +int +sixp_nbr_get_next_seqno(sixp_nbr_t *nbr) { assert(nbr != NULL); if(nbr == NULL) { - LOG_ERR("6P-nbr: sixp_nbr_get_gtx() fails because of invalid argument\n"); + LOG_ERR("6P-nbr: sixp_nbr_get_next_seqno() fails because of invalid arg\n"); return -1; } - return nbr->gen; + return nbr->next_seqno; } /*---------------------------------------------------------------------------*/ int -sixp_nbr_advance_gen(sixp_nbr_t *nbr) +sixp_nbr_set_next_seqno(sixp_nbr_t *nbr, uint16_t seqno) { assert(nbr != NULL); if(nbr == NULL) { - LOG_ERR("6P-nbr: sixp_nbr_advance_gen() fails because of invalid arg\n"); - return -1; - } - - if(nbr->gen == 0x00 || nbr->gen == 0x09) { - nbr->gen = 0x01; - } else if(nbr->gen < 0x09) { - nbr->gen++; - } else { - /* unexpected condition */ - LOG_ERR("6P-nbr: nbr %p has an invalid generation number %02x\n", - nbr, nbr->gen); + LOG_ERR("6P-nbr: sixp_nbr_set_next_seqno() fails because of invalid arg\n"); return -1; } + nbr->next_seqno = seqno; return 0; } /*---------------------------------------------------------------------------*/ int -sixp_nbr_get_next_seqno(sixp_nbr_t *nbr) +sixp_nbr_reset_next_seqno(sixp_nbr_t *nbr) { assert(nbr != NULL); if(nbr == NULL) { - LOG_ERR("6P-nbr: sixp_nbr_get_next_seqno() fails because of invalid arg\n"); + LOG_ERR("6P-nbr: sixp_nbr_clear_next_seqno() fails; invalid arg\n"); return -1; } - return nbr->next_seqno; + nbr->next_seqno = 0; + return 0; } /*---------------------------------------------------------------------------*/ int @@ -172,12 +161,12 @@ sixp_nbr_increment_next_seqno(sixp_nbr_t *nbr) return -1; } nbr->next_seqno++; - if(nbr->next_seqno > 0x0f) { + if(nbr->next_seqno == 0) { /* - * nbr->next_seqno, which represents a value of the SeqNum field, won't be - * larger than 0x0f since he length of SeqNum field is 4 bits. + * next_seqno can be 0 only by initialization of nbr or by a CLEAR + * transaction. */ - nbr->next_seqno = 0; + nbr->next_seqno = 1; } return 0; } @@ -186,7 +175,7 @@ int sixp_nbr_init(void) { sixp_nbr_t *nbr, *next_nbr; - if(nbr_table_is_register(sixp_nbrs) == 0) { + if(nbr_table_is_registered(sixp_nbrs) == 0) { nbr_table_register(sixp_nbrs, NULL); } else { /* remove all the existing nbrs */ diff --git a/os/net/mac/tsch/sixtop/sixp-nbr.h b/os/net/mac/tsch/sixtop/sixp-nbr.h index 739f35c9f31ddb19e5abe7506c80c1ddb7ddda13..817408028a069adfcc8f21c6065206ffec8bf6f3 100644 --- a/os/net/mac/tsch/sixtop/sixp-nbr.h +++ b/os/net/mac/tsch/sixtop/sixp-nbr.h @@ -63,25 +63,26 @@ sixp_nbr_t *sixp_nbr_alloc(const linkaddr_t *addr); void sixp_nbr_free(sixp_nbr_t *nbr); /** - * \brief Return GEN (Generation Number) of a neighbor + * \brief Get the next sequence number of a neighbor * \param nbr The pointer to a neighbor - * \return A value of GEN, -1 on failure + * \return A sequence number to use for a next request, -1 on failure */ -int16_t sixp_nbr_get_gen(sixp_nbr_t *nbr); +int16_t sixp_nbr_get_next_seqno(sixp_nbr_t *nbr); /** - * \brief Advance GTX of a neighbor + * \brief Set the specified value to the next sequence number of a neighbor * \param nbr The pointer to a neighbor + * \param seqno Value to be set * \return 0 on success, -1 on failure */ -int sixp_nbr_advance_gen(sixp_nbr_t *nbr); +int sixp_nbr_set_next_seqno(sixp_nbr_t *nbr, uint16_t seqno); /** - * \brief Get the next sequence number of a neighbor + * \brief Reset the next sequence number of a neighbor to zero * \param nbr The pointer to a neighbor - * \return A sequence number to use for a next request, -1 on failure + * \return 0 on success, -1 on failure */ -int16_t sixp_nbr_get_next_seqno(sixp_nbr_t *nbr); +int sixp_nbr_reset_next_seqno(sixp_nbr_t *nbr); /** * \brief Increment the next sequence number of a neighbor diff --git a/os/net/mac/tsch/sixtop/sixp-pkt.c b/os/net/mac/tsch/sixtop/sixp-pkt.c index 2d1dc485ba30164414408c3c8ca0615f83eac184..3cd5abd6c51307b61e0eccf92cba82c9a83a358e 100644 --- a/os/net/mac/tsch/sixtop/sixp-pkt.c +++ b/os/net/mac/tsch/sixtop/sixp-pkt.c @@ -67,6 +67,8 @@ static int32_t get_rel_cell_list_offset(sixp_pkt_type_t type, sixp_pkt_code_t code); static int32_t get_total_num_cells_offset(sixp_pkt_type_t type, sixp_pkt_code_t code); +static int32_t get_payload_offset(sixp_pkt_type_t type, + sixp_pkt_code_t code); /*---------------------------------------------------------------------------*/ static int32_t @@ -176,7 +178,21 @@ get_total_num_cells_offset(sixp_pkt_type_t type, sixp_pkt_code_t code) } return -1; } -/*---------------------------------------------------------------------------*/int +/*---------------------------------------------------------------------------*/ +static int32_t +get_payload_offset(sixp_pkt_type_t type, sixp_pkt_code_t code) +{ + if(type == SIXP_PKT_TYPE_REQUEST && code.value == SIXP_PKT_CMD_SIGNAL) { + return sizeof(sixp_pkt_metadata_t); + } else if((type == SIXP_PKT_TYPE_RESPONSE || + type == SIXP_PKT_TYPE_CONFIRMATION) && + code.value == SIXP_PKT_RC_SUCCESS) { + return 0; + } + return -1; +} +/*---------------------------------------------------------------------------*/ +int sixp_pkt_set_metadata(sixp_pkt_type_t type, sixp_pkt_code_t code, sixp_pkt_metadata_t metadata, uint8_t *body, uint16_t body_len) @@ -227,7 +243,7 @@ sixp_pkt_get_metadata(sixp_pkt_type_t type, sixp_pkt_code_t code, return -1; } - if(body_len < (offset + sizeof(*metadata))) { + if(body_len < offset + sizeof(*metadata)) { LOG_ERR("6P-pkt: cannot get metadata [type=%u, code=%u], ", type, code.value); LOG_ERR_("body is too short\n"); @@ -238,7 +254,7 @@ sixp_pkt_get_metadata(sixp_pkt_type_t type, sixp_pkt_code_t code, * Copy the content in the Metadata field as it is since 6P has no idea about * the internal structure of the field. */ - memcpy(metadata + offset, body, sizeof(*metadata)); + memcpy(metadata, body + offset, sizeof(*metadata)); return 0; } @@ -861,6 +877,73 @@ sixp_pkt_get_total_num_cells(sixp_pkt_type_t type, sixp_pkt_code_t code, } /*---------------------------------------------------------------------------*/ int +sixp_pkt_set_payload(sixp_pkt_type_t type, sixp_pkt_code_t code, + const uint8_t *payload, uint16_t payload_len, + uint8_t *body, uint16_t body_len) +{ + int32_t offset; + + if(body == NULL) { + LOG_ERR("6P-pkt: cannot set metadata; body is null\n"); + return -1; + } + + if((offset = get_payload_offset(type, code)) < 0) { + LOG_ERR("6P-pkt: cannot set payload [type=%u, code=%u], invalid type\n", + type, code.value); + return -1; + } + + if(body_len < (offset + payload_len)) { + LOG_ERR("6P-pkt: cannot set payload, body is too short [body_len=%u]\n", + body_len); + return -1; + } + + /* + * Copy the content into the Payload field as it is since 6P has no idea + * about the internal structure of the field. + */ + memcpy(body + offset, payload, payload_len); + + return 0; +} +/*---------------------------------------------------------------------------*/ +int +sixp_pkt_get_payload(sixp_pkt_type_t type, sixp_pkt_code_t code, + uint8_t *buf, uint16_t buf_len, + const uint8_t *body, uint16_t body_len) +{ + int32_t offset; + + if(buf == NULL || body == NULL) { + LOG_ERR("6P-pkt: cannot get payload; invalid argument\n"); + return -1; + } + + if((offset = get_payload_offset(type, code)) < 0) { + LOG_ERR("6P-pkt: cannot get payload [type=%u, code=%u], invalid type\n", + type, code.value); + return -1; + } + + if((body_len - offset) > buf_len) { + LOG_ERR("6P-pkt: cannot get payload [type=%u, code=%u], ", + type, code.value); + LOG_ERR_("buf_len is too short\n"); + return -1; + } + + /* + * Copy the content in the Payload field as it is since 6P has no idea about + * the internal structure of the field. + */ + memcpy(buf, body + offset, buf_len); + + return 0; +} +/*---------------------------------------------------------------------------*/ +int sixp_pkt_parse(const uint8_t *buf, uint16_t len, sixp_pkt_t *pkt) { @@ -870,24 +953,20 @@ sixp_pkt_parse(const uint8_t *buf, uint16_t len, return -1; } + memset(pkt, 0, sizeof(sixp_pkt_t)); + /* read the first 4 octets */ if(len < 4) { LOG_ERR("6P-pkt: sixp_pkt_parse() fails because it's a too short packet\n"); return -1; } - if((buf[0] & 0x0f) != SIXP_PKT_VERSION) { - LOG_ERR("6P-pkt: sixp_pkt_parse() fails because of invalid version [%u]\n", - buf[0] & 0x0f); - return -1; - } - - memset(pkt, 0, sizeof(sixp_pkt_t)); + /* parse the header as it's version 0 6P packet */ + pkt->version = buf[0] & 0x0f; pkt->type = (buf[0] & 0x30) >> 4; pkt->code.value = buf[1]; pkt->sfid = buf[2]; - pkt->seqno = buf[3] & 0x0f; - pkt->gen = (buf[3] & 0xf0) >> 4; + pkt->seqno = buf[3]; buf += 4; len -= 4; @@ -935,6 +1014,12 @@ sixp_pkt_parse(const uint8_t *buf, uint16_t len, return -1; } break; + case SIXP_PKT_CMD_SIGNAL: + if(len < sizeof(sixp_pkt_metadata_t)) { + LOG_ERR("6P-pkt: sixp_pkt_parse() fails because of invalid length\n"); + return -1; + } + break; case SIXP_PKT_CMD_CLEAR: if(len != sizeof(sixp_pkt_metadata_t)) { LOG_ERR("6P-pkt: sixp_pkt_parse() fails because of invalid length\n"); @@ -954,13 +1039,9 @@ sixp_pkt_parse(const uint8_t *buf, uint16_t len, * - Res to CLEAR: Empty (length 0) * - Res to STATUS: "Num. Cells" (total_num_cells) * - Res to ADD, DELETE, LIST: 0, 1, or multiple 6P cells + * - Res to SIGNAL: Payload (arbitrary length) */ - if(len != 0 && - len != sizeof(sixp_pkt_total_num_cells_t) && - (len % sizeof(uint32_t)) != 0) { - LOG_ERR("6P-pkt: sixp_pkt_parse() fails because of invalid length\n"); - return -1; - } + /* we accept any length because of SIGNAL */ break; case SIXP_PKT_RC_EOL: if((len % sizeof(uint32_t)) != 0) { @@ -968,14 +1049,14 @@ sixp_pkt_parse(const uint8_t *buf, uint16_t len, return -1; } break; - case SIXP_PKT_RC_ERROR: + case SIXP_PKT_RC_ERR: case SIXP_PKT_RC_RESET: - case SIXP_PKT_RC_VERSION: - case SIXP_PKT_RC_SFID: - case SIXP_PKT_RC_GEN: - case SIXP_PKT_RC_BUSY: - case SIXP_PKT_RC_NORES: - case SIXP_PKT_RC_CELLLIST: + case SIXP_PKT_RC_ERR_VERSION: + case SIXP_PKT_RC_ERR_SFID: + case SIXP_PKT_RC_ERR_SEQNUM: + case SIXP_PKT_RC_ERR_CELLLIST: + case SIXP_PKT_RC_ERR_BUSY: + case SIXP_PKT_RC_ERR_LOCKED: if(len != 0) { LOG_ERR("6P-pkt: sixp_pkt_parse() fails because of invalid length\n"); return -1; @@ -998,7 +1079,7 @@ sixp_pkt_parse(const uint8_t *buf, uint16_t len, /*---------------------------------------------------------------------------*/ int sixp_pkt_create(sixp_pkt_type_t type, sixp_pkt_code_t code, - uint8_t sfid, uint8_t seqno, uint8_t gen, + uint8_t sfid, uint8_t seqno, const uint8_t *body, uint16_t body_len, sixp_pkt_t *pkt) { uint8_t *hdr; @@ -1029,7 +1110,7 @@ sixp_pkt_create(sixp_pkt_type_t type, sixp_pkt_code_t code, hdr[0] = (type << 4) | SIXP_PKT_VERSION; hdr[1] = code.value; hdr[2] = sfid; - hdr[3] = (gen << 4) | seqno; + hdr[3] = seqno; /* data: write body */ if(body_len > 0 && body != NULL) { @@ -1043,7 +1124,6 @@ sixp_pkt_create(sixp_pkt_type_t type, sixp_pkt_code_t code, pkt->code = code; pkt->sfid = sfid; pkt->seqno = seqno; - pkt->gen = gen; pkt->body = body; pkt->body_len = body_len; } diff --git a/os/net/mac/tsch/sixtop/sixp-pkt.h b/os/net/mac/tsch/sixtop/sixp-pkt.h index 4966347082c4e91e01aa78fda79a310f5e755750..37bd91eaeb1c5889805cf7e0bf7dd0b0d1c6e914 100644 --- a/os/net/mac/tsch/sixtop/sixp-pkt.h +++ b/os/net/mac/tsch/sixtop/sixp-pkt.h @@ -46,6 +46,7 @@ #define SIXP_PKT_VERSION 0x00 /* typedefs for code readability */ +typedef uint8_t sixp_pkt_version_t; typedef uint8_t sixp_pkt_cell_options_t; typedef uint8_t sixp_pkt_num_cells_t; typedef uint8_t sixp_pkt_reserved_t; @@ -74,7 +75,8 @@ typedef enum { SIXP_PKT_CMD_RELOCATE = 0x03, /**< CMD_STATUS */ SIXP_PKT_CMD_COUNT = 0x04, /**< CMD_STATUS */ SIXP_PKT_CMD_LIST = 0x05, /**< CMD_LIST */ - SIXP_PKT_CMD_CLEAR = 0x06, /**< CMD_CLEAR */ + SIXP_PKT_CMD_SIGNAL = 0x06, /**< CMD_SIGNAL */ + SIXP_PKT_CMD_CLEAR = 0x07, /**< CMD_CLEAR */ SIXP_PKT_CMD_UNAVAILABLE = 0xff, /**< for internal use */ } sixp_pkt_cmd_t; @@ -82,16 +84,17 @@ typedef enum { * \brief 6P Return Codes */ typedef enum { - SIXP_PKT_RC_SUCCESS = 0x00, /**< RC_SUCCESS */ - SIXP_PKT_RC_ERROR = 0x01, /**< RC_ERROR */ - SIXP_PKT_RC_EOL = 0x02, /**< RC_EOL */ - SIXP_PKT_RC_RESET = 0x03, /**< RC_RESET */ - SIXP_PKT_RC_VERSION = 0x04, /**< RC_ERR_VER */ - SIXP_PKT_RC_SFID = 0x05, /**< RC_ERR_SFID */ - SIXP_PKT_RC_GEN = 0x06, /**< RC_ERR_GEN */ - SIXP_PKT_RC_BUSY = 0x07, /**< RC_ERR_BUSY */ - SIXP_PKT_RC_NORES = 0x08, /**< RC_ERR_NORES */ - SIXP_PKT_RC_CELLLIST = 0x09, /**< RC_ERR_CELLLIST */ + SIXP_PKT_RC_SUCCESS = 0x00, /**< RC_SUCCESS */ + SIXP_PKT_RC_EOL = 0x01, /**< RC_EOL */ + SIXP_PKT_RC_ERR = 0x02, /**< RC_ERR */ + SIXP_PKT_RC_RESET = 0x03, /**< RC_RESET */ + SIXP_PKT_RC_ERR_VERSION = 0x04, /**< RC_ERR_VERSION */ + SIXP_PKT_RC_ERR_SFID = 0x05, /**< RC_ERR_SFID */ + SIXP_PKT_RC_ERR_SEQNUM = 0x06, /**< RC_ERR_SEQNUM */ + SIXP_PKT_RC_ERR_CELLLIST = 0x07, /**< RC_ERR_CELLLIST */ + SIXP_PKT_RC_ERR_BUSY = 0x08, /**< RC_ERR_BUSY */ + SIXP_PKT_RC_ERR_LOCKED = 0x09, /**< RC_ERR_LOCKED */ + } sixp_pkt_rc_t; /** @@ -116,13 +119,13 @@ typedef enum { * \brief 6top IE Structure */ typedef struct { - sixp_pkt_type_t type; /**< Type */ - sixp_pkt_code_t code; /**< Code */ - uint8_t sfid; /**< SFID */ - uint8_t seqno; /**< SeqNum */ - uint8_t gen; /**< GEN */ - const uint8_t *body; /**< Other Fields... */ - uint16_t body_len; /**< The length of Other Fields */ + sixp_pkt_version_t version; /**< Version */ + sixp_pkt_type_t type; /**< Type */ + sixp_pkt_code_t code; /**< Code */ + uint8_t sfid; /**< SFID */ + uint8_t seqno; /**< SeqNum */ + const uint8_t *body; /**< Other Fields... */ + uint16_t body_len; /**< The length of Other Fields */ } sixp_pkt_t; /** @@ -413,6 +416,34 @@ int sixp_pkt_get_total_num_cells(sixp_pkt_type_t type, sixp_pkt_code_t code, sixp_pkt_total_num_cells_t *total_num_cells, const uint8_t *body, uint16_t body_len); +/** + * \brief Write Payload in "Other Fields" of 6P packet + * \param type 6P Message Type + * \param code 6P Command Identifier or Return Code + * \param payload "Payload" to write + * \param payload_len The length of "Payload" to write + * \param body The pointer to buffer pointing to "Other Fields" + * \param body_len The length of body, typically "Other Fields" length + * \return 0 on success, -1 on failure + */ +int sixp_pkt_set_payload(sixp_pkt_type_t type, sixp_pkt_code_t code, + const uint8_t *payload, uint16_t payload_len, + uint8_t *body, uint16_t body_len); + +/** + * \brief Read Payload in "Other Fields" of 6P packet + * \param type 6P Message Type + * \param code 6P Command Identifier or Return Code + * \param buf The pointer to buffer to store "Payload" in + * \param buf_len The length of buf + * \param body The pointer to buffer pointing to "Other Fields" + * \param body_len The length of body, typically "Other Fields" length + * \return 0 on success, -1 on failure + */ +int sixp_pkt_get_payload(sixp_pkt_type_t type, sixp_pkt_code_t code, + uint8_t *buf, uint16_t buf_len, + const uint8_t *body, uint16_t body_len); + /** * \brief Parse a 6P packet * \param buf The pointer to a buffer pointing 6top IE Content @@ -429,7 +460,6 @@ int sixp_pkt_parse(const uint8_t *buf, uint16_t len, * \param code 6P Message Code, Command Identifier or Return Code * \param sfid Scheduling Function Identifier * \param seqno Sequence Number - * \param gen GEN * \param body The pointer to "Other Fields" in a buffer * \param body_len The length of body, typically "Other Fields" length * \param pkt The pointer to a sixp_pkt_t structure to store packet info @@ -437,7 +467,7 @@ int sixp_pkt_parse(const uint8_t *buf, uint16_t len, * \return 0 on success, -1 on failure */ int sixp_pkt_create(sixp_pkt_type_t type, sixp_pkt_code_t code, - uint8_t sfid, uint8_t seqno, uint8_t gen, + uint8_t sfid, uint8_t seqno, const uint8_t *body, uint16_t body_len, sixp_pkt_t *pkt); diff --git a/os/net/mac/tsch/sixtop/sixp-trans.c b/os/net/mac/tsch/sixtop/sixp-trans.c index feb2c063139a2919c0911d91f31a1684048a4f25..cd15a00d750a0d4093a4b93fff77b0f5bd07f085 100644 --- a/os/net/mac/tsch/sixtop/sixp-trans.c +++ b/os/net/mac/tsch/sixtop/sixp-trans.c @@ -43,6 +43,7 @@ #include "sixtop.h" #include "sixtop-conf.h" +#include "sixp-nbr.h" #include "sixp-trans.h" /* Log configuration */ @@ -204,6 +205,8 @@ determine_trans_mode(const sixp_pkt_t *req) int sixp_trans_transit_state(sixp_trans_t *trans, sixp_trans_state_t new_state) { + sixp_nbr_t *nbr; + assert(trans != NULL); if(trans == NULL) { LOG_ERR("6top: invalid argument, trans is NULL\n"); @@ -228,6 +231,34 @@ sixp_trans_transit_state(sixp_trans_t *trans, sixp_trans_state_t new_state) trans->mode == SIXP_TRANS_MODE_3_STEP)) { LOG_INFO("6P-trans: trans %p state changes from %u to %u\n", trans, trans->state, new_state); + + if(new_state == SIXP_TRANS_STATE_REQUEST_SENT) { + /* + * that is, the request is acknowledged by the peer; increment + * next_seqno + */ + if((nbr = sixp_nbr_find(&trans->peer_addr)) == NULL) { + LOG_ERR("6top: cannot increment next_seqno\n"); + } else { + if(trans->cmd == SIXP_PKT_CMD_CLEAR) { + /* next_seqno must have been reset to 0 already. */ + assert(sixp_nbr_get_next_seqno(nbr) == 0); + } else { + sixp_nbr_increment_next_seqno(nbr); + } + } + } else if(new_state == SIXP_TRANS_STATE_RESPONSE_SENT) { + if((nbr = sixp_nbr_find(&trans->peer_addr)) == NULL) { + LOG_ERR("6top: cannot update next_seqno\n"); + } else { + /* override next_seqno with the received one unless it's zero */ + if(trans->seqno != 0) { + sixp_nbr_set_next_seqno(nbr, trans->seqno); + } + sixp_nbr_increment_next_seqno(nbr); + } + } + trans->state = new_state; schedule_trans_process(trans); return 0; diff --git a/os/net/mac/tsch/sixtop/sixp.c b/os/net/mac/tsch/sixtop/sixp.c index 8afe8eb2aa518030711dac5c50ac463e83f2019f..e8c8c49b0dabbb7d2e52cf7a49601d1893495a4b 100644 --- a/os/net/mac/tsch/sixtop/sixp.c +++ b/os/net/mac/tsch/sixtop/sixp.c @@ -122,7 +122,7 @@ send_back_error(sixp_pkt_type_t type, sixp_pkt_code_t code, const linkaddr_t *dest_addr) { /* create a 6P packet within packetbuf */ - if(sixp_pkt_create(type, code, sfid, seqno, 0, NULL, 0, NULL) < 0) { + if(sixp_pkt_create(type, code, sfid, seqno, NULL, 0, NULL) < 0) { LOG_ERR("6P: failed to create a 6P packet to return an error [rc:%u]\n", code.value); return -1; @@ -136,12 +136,10 @@ void sixp_input(const uint8_t *buf, uint16_t len, const linkaddr_t *src_addr) { sixp_pkt_t pkt; - sixp_nbr_t *nbr; - uint8_t invalid_schedule_generation; sixp_trans_t *trans; + sixp_nbr_t *nbr; const sixtop_sf_t *sf; int16_t seqno; - int16_t gen; int ret; assert(buf != NULL && src_addr != NULL); @@ -150,7 +148,17 @@ sixp_input(const uint8_t *buf, uint16_t len, const linkaddr_t *src_addr) } if(sixp_pkt_parse(buf, len, &pkt) < 0) { - LOG_ERR("6P: sixp_input() fails because off a malformed 6P packet\n"); + if(pkt.version != SIXP_PKT_VERSION) { + LOG_ERR("6P: sixp_input() unsupported version %u\n", pkt.version); + if(send_back_error(SIXP_PKT_TYPE_RESPONSE, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR_VERSION, + pkt.sfid, pkt.seqno, + src_addr) < 0) { + LOG_ERR("6P: sixp_input() fails to send RC_ERR_VERSION\n"); + return; + } + } + LOG_ERR("6P: sixp_input() fails because of a malformed 6P packet\n"); return; } @@ -170,43 +178,13 @@ sixp_input(const uint8_t *buf, uint16_t len, const linkaddr_t *src_addr) * sent back? */ if(send_back_error(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SFID, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR_SFID, pkt.sfid, pkt.seqno, src_addr) < 0) { LOG_ERR("6P: sixp_input() fails to return an error response\n"); }; return; } - nbr = sixp_nbr_find(src_addr); - /* Generation Management */ - if(pkt.code.value == SIXP_PKT_CMD_CLEAR) { - /* Not need to validate generation counters in a case of CMD_CLEAR */ - invalid_schedule_generation = 0; - } else if(nbr == NULL) { - if(pkt.gen == 0) { - invalid_schedule_generation = 0; /* valid combination */ - } else { - LOG_ERR("6P: GEN should be 0 because of no corresponding nbr\n"); - invalid_schedule_generation = 1; - } - } else { - if((gen = sixp_nbr_get_gen(nbr)) < 0) { - LOG_ERR("6P: unexpected error; cannot get our GEN\n"); - return; - } - LOG_INFO("6P: received GEN %u, our GEN: %u\n", - pkt.gen, sixp_nbr_get_gen(nbr)); - if(pkt.gen == gen) { - invalid_schedule_generation = 0; /* valid combination */ - } else { - invalid_schedule_generation = 1; - } - } - if(invalid_schedule_generation) { - LOG_ERR("6P: sixp_input() fails because of schedule generation mismatch\n"); - return; - } - /* Transaction Management */ trans = sixp_trans_find(src_addr); @@ -217,20 +195,51 @@ sixp_input(const uint8_t *buf, uint16_t len, const linkaddr_t *src_addr) LOG_ERR_LLADDR((const linkaddr_t *)src_addr); LOG_ERR_(" seqno:%u] is in process\n", sixp_trans_get_seqno(trans)); if(send_back_error(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_BUSY, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR_BUSY, pkt.sfid, pkt.seqno, src_addr) < 0) { LOG_ERR("6P: sixp_input() fails to return an error response"); } return; - } else if((trans = sixp_trans_alloc(&pkt, src_addr)) == NULL) { + } + + if((pkt.code.cmd == SIXP_PKT_CMD_CLEAR) && + (nbr = sixp_nbr_find(src_addr)) != NULL) { + LOG_INFO("6P: sixp_input() reset nbr's next_seqno by CLEAR Request\n"); + sixp_nbr_reset_next_seqno(nbr); + } + + if((trans = sixp_trans_alloc(&pkt, src_addr)) == NULL) { LOG_ERR("6P: sixp_input() fails because of lack of memory\n"); if(send_back_error(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_NORES, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR_BUSY, pkt.sfid, pkt.seqno, src_addr) < 0) { LOG_ERR("6P: sixp_input() fails to return an error response\n"); } return; } + + /* Inconsistency Management */ + if(pkt.code.cmd != SIXP_PKT_CMD_CLEAR && + (((nbr = sixp_nbr_find(src_addr)) == NULL && + (pkt.seqno != 0)) || + ((nbr != NULL) && + (sixp_nbr_get_next_seqno(nbr) != 0) && + pkt.seqno == 0))) { + if(trans != NULL) { + sixp_trans_transit_state(trans, + SIXP_TRANS_STATE_REQUEST_RECEIVED); + + } + if(send_back_error(SIXP_PKT_TYPE_RESPONSE, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR_SEQNUM, + pkt.sfid, + nbr == NULL ? 0 : sixp_nbr_get_next_seqno(nbr), + src_addr) < 0) { + LOG_ERR("6P: sixp_input() fails to return an error response\n"); + } + return; + } + } else if(pkt.type == SIXP_PKT_TYPE_RESPONSE || pkt.type == SIXP_PKT_TYPE_CONFIRMATION) { if(trans == NULL) { @@ -290,7 +299,7 @@ sixp_output(sixp_pkt_type_t type, sixp_pkt_code_t code, uint8_t sfid, sixp_trans_t *trans; sixp_nbr_t *nbr; sixp_pkt_cmd_t cmd; - int16_t seqno, gen; + int16_t seqno; sixp_pkt_t pkt; assert(dest_addr != NULL); @@ -324,7 +333,7 @@ sixp_output(sixp_pkt_type_t type, sixp_pkt_code_t code, uint8_t sfid, if(trans == NULL) { LOG_ERR("6P: sixp_output() fails because of no transaction [peer_addr:"); LOG_ERR_LLADDR((const linkaddr_t *)dest_addr); - LOG_ERR_("\n"); + LOG_ERR_("]\n"); return -1; } else if(sixp_trans_get_state(trans) != SIXP_TRANS_STATE_RESPONSE_RECEIVED) { @@ -365,9 +374,9 @@ sixp_output(sixp_pkt_type_t type, sixp_pkt_code_t code, uint8_t sfid, LOG_ERR("6P: sixp_output() fails to get the next sequence number\n"); return -1; } - if(sixp_nbr_increment_next_seqno(nbr) < 0) { - LOG_ERR("6P: sixp_output() fails to increment the next sequence number\n"); - return -1; + if(code.cmd == SIXP_PKT_CMD_CLEAR) { + LOG_INFO("6P: sixp_output() reset nbr's next_seqno by CLEAR Request\n"); + sixp_nbr_reset_next_seqno(nbr); } } else { assert(trans != NULL); @@ -377,17 +386,9 @@ sixp_output(sixp_pkt_type_t type, sixp_pkt_code_t code, uint8_t sfid, } } - /* set GEN */ - if(nbr == NULL) { - gen = 0; - } else if((gen = sixp_nbr_get_gen(nbr)) < 0) { - LOG_ERR("6P: sixp_output() fails to get GEN\n"); - return -1; - } - /* create a 6P packet within packetbuf */ if(sixp_pkt_create(type, code, sfid, - (uint8_t)seqno, (uint8_t)gen, + (uint8_t)seqno, body, body_len, type == SIXP_PKT_TYPE_REQUEST ? &pkt : NULL) < 0) { LOG_ERR("6P: sixp_output() fails to create a 6P packet\n"); diff --git a/os/net/mac/tsch/tsch-adaptive-timesync.c b/os/net/mac/tsch/tsch-adaptive-timesync.c index 186d8d7ba8e24e34ad71e8f765e8a0071af6d0f3..a23a4f1b0f783636e8f1cd1c04f182089426d67a 100644 --- a/os/net/mac/tsch/tsch-adaptive-timesync.c +++ b/os/net/mac/tsch/tsch-adaptive-timesync.c @@ -44,9 +44,6 @@ */ #include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-conf.h" -#include "net/mac/tsch/tsch-adaptive-timesync.h" -#include "net/mac/tsch/tsch-log.h" #include <stdio.h> #if TSCH_ADAPTIVE_TIMESYNC diff --git a/os/net/mac/tsch/tsch-adaptive-timesync.h b/os/net/mac/tsch/tsch-adaptive-timesync.h index e8398fdc2d9be68beaa3e4fd47481b711dc13c60..c4ca20b7bff82bfaee9491041fc06fe6afa08e44 100644 --- a/os/net/mac/tsch/tsch-adaptive-timesync.h +++ b/os/net/mac/tsch/tsch-adaptive-timesync.h @@ -33,6 +33,8 @@ /** * \addtogroup tsch * @{ + * \file + * TSCH adaptive time synchronization */ #ifndef __TSCH_ADAPTIVE_TIMESYNC_H__ @@ -41,56 +43,33 @@ /********** Includes **********/ #include "contiki.h" -#include "net/mac/tsch/tsch-private.h" - -/******** Configuration *******/ - -/* Use SFD timestamp for synchronization? By default we merely rely on rtimer and busy wait - * until SFD is high, which we found to provide greater accuracy on JN516x and CC2420. - * Note: for association, however, we always use SFD timestamp to know the time of arrival - * of the EB (because we do not busy-wait for the whole scanning process) - * */ -#ifdef TSCH_CONF_RESYNC_WITH_SFD_TIMESTAMPS -#define TSCH_RESYNC_WITH_SFD_TIMESTAMPS TSCH_CONF_RESYNC_WITH_SFD_TIMESTAMPS -#else -#define TSCH_RESYNC_WITH_SFD_TIMESTAMPS 0 -#endif - -/* If enabled, remove jitter due to measurement errors */ -#ifdef TSCH_CONF_TIMESYNC_REMOVE_JITTER -#define TSCH_TIMESYNC_REMOVE_JITTER TSCH_CONF_TIMESYNC_REMOVE_JITTER -#else -#define TSCH_TIMESYNC_REMOVE_JITTER TSCH_RESYNC_WITH_SFD_TIMESTAMPS -#endif - -/* The jitter to remove in ticks. - * This should be the sum of measurement errors on Tx and Rx nodes. - * */ -#define TSCH_TIMESYNC_MEASUREMENT_ERROR US_TO_RTIMERTICKS(32) - -/* Base drift value. - * Used to compensate locally know inaccuracies, such as - * the effect of having a binary 32.768 kHz timer as the TSCH time base. */ -#ifdef TSCH_CONF_BASE_DRIFT_PPM -#define TSCH_BASE_DRIFT_PPM TSCH_CONF_BASE_DRIFT_PPM -#else -#define TSCH_BASE_DRIFT_PPM 0 -#endif - -/* The approximate number of slots per second */ -#define TSCH_SLOTS_PER_SECOND (1000000 / TSCH_DEFAULT_TS_TIMESLOT_LENGTH) /***** External Variables *****/ -/* The neighbor last used as our time source */ +/** \brief The neighbor last used as our time source */ extern struct tsch_neighbor *last_timesource_neighbor; /********** Functions *********/ +/** + * \brief Updates timesync information for a given neighbor + * \param n The neighbor + * \param time_delta_asn ASN time delta since last synchronization, i.e. number of slots elapsed + * \param drift_correction The measured drift in ticks since last synchronization + */ void tsch_timesync_update(struct tsch_neighbor *n, uint16_t time_delta_asn, int32_t drift_correction); +/** + * \brief Computes time compensation for a given point in the future + * \param delta_ticks The number of ticks in the future we want to calculate compensation for + * \return The time compensation + */ int32_t tsch_timesync_adaptive_compensate(rtimer_clock_t delta_ticks); +/** + * \brief Gives the estimated clock drift w.r.t. the time source in PPM (parts per million) + * \return The time drift in PPM + */ long int tsch_adaptive_timesync_get_drift_ppm(void); #endif /* __TSCH_ADAPTIVE_TIMESYNC_H__ */ diff --git a/os/net/mac/tsch/tsch-asn.h b/os/net/mac/tsch/tsch-asn.h index 9895cdcf4695d62d7e8a56f103809f0dd77686e3..1db99b43270a699f4565ae7142ba9be78c1d6027 100644 --- a/os/net/mac/tsch/tsch-asn.h +++ b/os/net/mac/tsch/tsch-asn.h @@ -31,16 +31,12 @@ */ /** + * \addtogroup tsch + * @{ * \file * TSCH 5-Byte Absolute Slot Number (ASN) management * \author * Simon Duquennoy <simonduq@sics.se> - * - */ - -/** - * \addtogroup tsch - * @{ */ #ifndef __TSCH_ASN_H__ @@ -48,13 +44,13 @@ /************ Types ***********/ -/* The ASN is an absolute slot number over 5 bytes. */ +/** \brief The ASN is an absolute slot number over 5 bytes. */ struct tsch_asn_t { uint32_t ls4b; /* least significant 4 bytes */ uint8_t ms1b; /* most significant 1 byte */ }; -/* For quick modulo operation on ASN */ +/** \brief For quick modulo operation on ASN */ struct tsch_asn_divisor_t { uint16_t val; /* Divisor value */ uint16_t asn_ms1b_remainder; /* Remainder of the operation 0x100000000 / val */ @@ -62,37 +58,37 @@ struct tsch_asn_divisor_t { /************ Macros **********/ -/* Initialize ASN */ +/** \brief Initialize ASN */ #define TSCH_ASN_INIT(asn, ms1b_, ls4b_) do { \ (asn).ms1b = (ms1b_); \ (asn).ls4b = (ls4b_); \ } while(0); -/* Increment an ASN by inc (32 bits) */ +/** \brief Increment an ASN by inc (32 bits) */ #define TSCH_ASN_INC(asn, inc) do { \ uint32_t new_ls4b = (asn).ls4b + (inc); \ if(new_ls4b < (asn).ls4b) { (asn).ms1b++; } \ (asn).ls4b = new_ls4b; \ } while(0); -/* Decrement an ASN by inc (32 bits) */ +/** \brief Decrement an ASN by inc (32 bits) */ #define TSCH_ASN_DEC(asn, dec) do { \ uint32_t new_ls4b = (asn).ls4b - (dec); \ if(new_ls4b > (asn).ls4b) { (asn).ms1b--; } \ (asn).ls4b = new_ls4b; \ } while(0); -/* Returns the 32-bit diff between asn1 and asn2 */ +/** \brief Returns the 32-bit diff between asn1 and asn2 */ #define TSCH_ASN_DIFF(asn1, asn2) \ ((asn1).ls4b - (asn2).ls4b) -/* Initialize a struct asn_divisor_t */ +/** \brief Initialize a struct asn_divisor_t */ #define TSCH_ASN_DIVISOR_INIT(div, val_) do { \ (div).val = (val_); \ (div).asn_ms1b_remainder = ((0xffffffff % (val_)) + 1) % (val_); \ } while(0); -/* Returns the result (16 bits) of a modulo operation on ASN, +/** \brief Returns the result (16 bits) of a modulo operation on ASN, * with divisor being a struct asn_divisor_t */ #define TSCH_ASN_MOD(asn, div) \ ((uint16_t)((asn).ls4b % (div).val) \ diff --git a/os/net/mac/tsch/tsch-conf.h b/os/net/mac/tsch/tsch-conf.h index 2934738b8d4aa71bbd8680a022baeef5e60c8a56..3ee47b9cbd669c8a0dca8bc8a0bc63e785bffbcd 100644 --- a/os/net/mac/tsch/tsch-conf.h +++ b/os/net/mac/tsch/tsch-conf.h @@ -31,17 +31,14 @@ */ /** +* \addtogroup tsch +* @{ * \file * TSCH configuration * \author * Simon Duquennoy <simonduq@sics.se> */ -/** - * \addtogroup tsch - * @{ -*/ - #ifndef __TSCH_CONF_H__ #define __TSCH_CONF_H__ @@ -49,19 +46,91 @@ #include "contiki.h" -/******** Configuration *******/ +/******** Configuration: synchronization *******/ + +/* Max time before sending a unicast keep-alive message to the time source */ +#ifdef TSCH_CONF_KEEPALIVE_TIMEOUT +#define TSCH_KEEPALIVE_TIMEOUT TSCH_CONF_KEEPALIVE_TIMEOUT +#else +/* Time to desynch assuming a drift of 40 PPM (80 PPM between two nodes) and guard time of +/-1ms: 12.5s. */ +#define TSCH_KEEPALIVE_TIMEOUT (12 * CLOCK_SECOND) +#endif + +/* With TSCH_ADAPTIVE_TIMESYNC enabled: keep-alive timeout used after reaching + * accurate drift compensation. */ +#ifdef TSCH_CONF_MAX_KEEPALIVE_TIMEOUT +#define TSCH_MAX_KEEPALIVE_TIMEOUT TSCH_CONF_MAX_KEEPALIVE_TIMEOUT +#else +#define TSCH_MAX_KEEPALIVE_TIMEOUT (60 * CLOCK_SECOND) +#endif + +/* Max time without synchronization before leaving the PAN */ +#ifdef TSCH_CONF_DESYNC_THRESHOLD +#define TSCH_DESYNC_THRESHOLD TSCH_CONF_DESYNC_THRESHOLD +#else +#define TSCH_DESYNC_THRESHOLD (2 * TSCH_MAX_KEEPALIVE_TIMEOUT) +#endif + +/* Period between two consecutive EBs */ +#ifdef TSCH_CONF_EB_PERIOD +#define TSCH_EB_PERIOD TSCH_CONF_EB_PERIOD +#else +#define TSCH_EB_PERIOD (16 * CLOCK_SECOND) +#endif + +/* Max Period between two consecutive EBs */ +#ifdef TSCH_CONF_MAX_EB_PERIOD +#define TSCH_MAX_EB_PERIOD TSCH_CONF_MAX_EB_PERIOD +#else +#define TSCH_MAX_EB_PERIOD (16 * CLOCK_SECOND) +#endif + +/* Use SFD timestamp for synchronization? By default we merely rely on rtimer and busy wait + * until SFD is high, which we found to provide greater accuracy on JN516x and CC2420. + * Note: for association, however, we always use SFD timestamp to know the time of arrival + * of the EB (because we do not busy-wait for the whole scanning process) + * */ +#ifdef TSCH_CONF_RESYNC_WITH_SFD_TIMESTAMPS +#define TSCH_RESYNC_WITH_SFD_TIMESTAMPS TSCH_CONF_RESYNC_WITH_SFD_TIMESTAMPS +#else +#define TSCH_RESYNC_WITH_SFD_TIMESTAMPS 0 +#endif + +/* If enabled, remove jitter due to measurement errors */ +#ifdef TSCH_CONF_TIMESYNC_REMOVE_JITTER +#define TSCH_TIMESYNC_REMOVE_JITTER TSCH_CONF_TIMESYNC_REMOVE_JITTER +#else +#define TSCH_TIMESYNC_REMOVE_JITTER TSCH_RESYNC_WITH_SFD_TIMESTAMPS +#endif + +/* Base drift value. + * Used to compensate locally know inaccuracies, such as + * the effect of having a binary 32.768 kHz timer as the TSCH time base. */ +#ifdef TSCH_CONF_BASE_DRIFT_PPM +#define TSCH_BASE_DRIFT_PPM TSCH_CONF_BASE_DRIFT_PPM +#else +#define TSCH_BASE_DRIFT_PPM 0 +#endif + +/* Estimate the drift of the time-source neighbor and compensate for it? */ +#ifdef TSCH_CONF_ADAPTIVE_TIMESYNC +#define TSCH_ADAPTIVE_TIMESYNC TSCH_CONF_ADAPTIVE_TIMESYNC +#else +#define TSCH_ADAPTIVE_TIMESYNC 1 +#endif + +/* An ad-hoc mechanism to have TSCH select its time source without the + * help of an upper-layer, simply by collecting statistics on received + * EBs and their join priority. Disabled by default as we recomment + * mapping the time source on the RPL preferred parent + * (via tsch_rpl_callback_parent_switch) */ +#ifdef TSCH_CONF_AUTOSELECT_TIME_SOURCE +#define TSCH_AUTOSELECT_TIME_SOURCE TSCH_CONF_AUTOSELECT_TIME_SOURCE +#else +#define TSCH_AUTOSELECT_TIME_SOURCE 0 +#endif /* TSCH_CONF_EB_AUTOSELECT */ -/* Default IEEE 802.15.4e hopping sequences, obtained from https://gist.github.com/twatteyne/2e22ee3c1a802b685695 */ -/* 16 channels, sequence length 16 */ -#define TSCH_HOPPING_SEQUENCE_16_16 (uint8_t[]){ 16, 17, 23, 18, 26, 15, 25, 22, 19, 11, 12, 13, 24, 14, 20, 21 } -/* 4 channels, sequence length 16 */ -#define TSCH_HOPPING_SEQUENCE_4_16 (uint8_t[]){ 20, 26, 25, 26, 15, 15, 25, 20, 26, 15, 26, 25, 20, 15, 20, 25 } -/* 4 channels, sequence length 4 */ -#define TSCH_HOPPING_SEQUENCE_4_4 (uint8_t[]){ 15, 25, 26, 20 } -/* 2 channels, sequence length 2 */ -#define TSCH_HOPPING_SEQUENCE_2_2 (uint8_t[]){ 20, 25 } -/* 1 channel, sequence length 1 */ -#define TSCH_HOPPING_SEQUENCE_1_1 (uint8_t[]){ 20 } +/******** Configuration: channel hopping *******/ /* Default hopping sequence, used in case hopping sequence ID == 0 */ #ifdef TSCH_CONF_DEFAULT_HOPPING_SEQUENCE @@ -85,86 +154,195 @@ #define TSCH_HOPPING_SEQUENCE_MAX_LEN 16 #endif -/* Timeslot timing */ +/******** Configuration: association *******/ -#ifndef TSCH_CONF_DEFAULT_TIMESLOT_LENGTH -#define TSCH_CONF_DEFAULT_TIMESLOT_LENGTH 10000 -#endif /* TSCH_CONF_DEFAULT_TIMESLOT_LENGTH */ +/* Start TSCH automatically after init? If not, the upper layers + * must call NETSTACK_MAC.on() to start it. Useful when the + * application needs to control when the nodes are to start + * scanning or advertising.*/ +#ifdef TSCH_CONF_AUTOSTART +#define TSCH_AUTOSTART TSCH_CONF_AUTOSTART +#else +#define TSCH_AUTOSTART 1 +#endif -/* Configurable Rx guard time is micro-seconds */ -#ifndef TSCH_CONF_RX_WAIT -#define TSCH_CONF_RX_WAIT 2200 -#endif /* TSCH_CONF_RX_WAIT */ +/* Max acceptable join priority */ +#ifdef TSCH_CONF_MAX_JOIN_PRIORITY +#define TSCH_MAX_JOIN_PRIORITY TSCH_CONF_MAX_JOIN_PRIORITY +#else +#define TSCH_MAX_JOIN_PRIORITY 32 +#endif -/* The default timeslot timing in the standard is a guard time of - * 2200 us, a Tx offset of 2120 us and a Rx offset of 1120 us. - * As a result, the listening device has a guard time not centered - * on the expected Tx time. This is to be fixed in the next iteration - * of the standard. This can be enabled with: - * #define TSCH_DEFAULT_TS_TX_OFFSET 2120 - * #define TSCH_DEFAULT_TS_RX_OFFSET 1120 - * #define TSCH_DEFAULT_TS_RX_WAIT 2200 - * - * Instead, we align the Rx guard time on expected Tx time. The Rx - * guard time is user-configurable with TSCH_CONF_RX_WAIT. - - * (TS_TX_OFFSET - (TS_RX_WAIT / 2)) instead */ - -#if TSCH_CONF_DEFAULT_TIMESLOT_LENGTH == 10000 -/* Default timeslot timing as per IEEE 802.15.4e */ - -#define TSCH_DEFAULT_TS_CCA_OFFSET 1800 -#define TSCH_DEFAULT_TS_CCA 128 -#define TSCH_DEFAULT_TS_TX_OFFSET 2120 -#define TSCH_DEFAULT_TS_RX_OFFSET (TSCH_DEFAULT_TS_TX_OFFSET - (TSCH_CONF_RX_WAIT / 2)) -#define TSCH_DEFAULT_TS_RX_ACK_DELAY 800 -#define TSCH_DEFAULT_TS_TX_ACK_DELAY 1000 -#define TSCH_DEFAULT_TS_RX_WAIT TSCH_CONF_RX_WAIT -#define TSCH_DEFAULT_TS_ACK_WAIT 400 -#define TSCH_DEFAULT_TS_RX_TX 192 -#define TSCH_DEFAULT_TS_MAX_ACK 2400 -#define TSCH_DEFAULT_TS_MAX_TX 4256 -#define TSCH_DEFAULT_TS_TIMESLOT_LENGTH 10000 - -#elif TSCH_CONF_DEFAULT_TIMESLOT_LENGTH == 15000 -/* Default timeslot timing for platforms requiring 15ms slots */ - -#define TSCH_DEFAULT_TS_CCA_OFFSET 1800 -#define TSCH_DEFAULT_TS_CCA 128 -#define TSCH_DEFAULT_TS_TX_OFFSET 4000 -#define TSCH_DEFAULT_TS_RX_OFFSET (TSCH_DEFAULT_TS_TX_OFFSET - (TSCH_CONF_RX_WAIT / 2)) -#define TSCH_DEFAULT_TS_RX_ACK_DELAY 3600 -#define TSCH_DEFAULT_TS_TX_ACK_DELAY 4000 -#define TSCH_DEFAULT_TS_RX_WAIT TSCH_CONF_RX_WAIT -#define TSCH_DEFAULT_TS_ACK_WAIT 800 -#define TSCH_DEFAULT_TS_RX_TX 2072 -#define TSCH_DEFAULT_TS_MAX_ACK 2400 -#define TSCH_DEFAULT_TS_MAX_TX 4256 -#define TSCH_DEFAULT_TS_TIMESLOT_LENGTH 15000 - -#elif TSCH_CONF_DEFAULT_TIMESLOT_LENGTH == 65000U -/* 65ms timeslot, i.e. nearly the max length allowed by standard (16-bit unsigned in micro-seconds). - * Useful for running link-layer security on sky in Cooja, where only S/W security is supported. - * Note: this slot timing would require a total of 120ms. If a slot overlaps with the next active slot, - * the latter will be skipped. - * This configuration is mostly a work-around to test link-layer security in Cooja, it is recommended - * to use it with a 6TiSCH minimal schedule of length >= 2. */ - -#define TSCH_DEFAULT_TS_CCA_OFFSET 1800 -#define TSCH_DEFAULT_TS_CCA 128 -#define TSCH_DEFAULT_TS_TX_OFFSET 52000 -#define TSCH_DEFAULT_TS_RX_OFFSET (TSCH_DEFAULT_TS_TX_OFFSET - (TSCH_CONF_RX_WAIT / 2)) -#define TSCH_DEFAULT_TS_RX_ACK_DELAY 58600 -#define TSCH_DEFAULT_TS_TX_ACK_DELAY 59000 -#define TSCH_DEFAULT_TS_RX_WAIT TSCH_CONF_RX_WAIT -#define TSCH_DEFAULT_TS_ACK_WAIT 800 -#define TSCH_DEFAULT_TS_RX_TX 2072 -#define TSCH_DEFAULT_TS_MAX_ACK 2400 -#define TSCH_DEFAULT_TS_MAX_TX 4256 -#define TSCH_DEFAULT_TS_TIMESLOT_LENGTH 65000 - -#else -#error "TSCH: Unsupported default timeslot length" +/* Join only secured networks? (discard EBs with security disabled) */ +#ifdef TSCH_CONF_JOIN_SECURED_ONLY +#define TSCH_JOIN_SECURED_ONLY TSCH_CONF_JOIN_SECURED_ONLY +#else +/* By default, set if LLSEC802154_ENABLED is also non-zero */ +#define TSCH_JOIN_SECURED_ONLY LLSEC802154_ENABLED +#endif + +/* By default, join any PAN ID. Otherwise, wait for an EB from IEEE802154_PANID */ +#ifdef TSCH_CONF_JOIN_MY_PANID_ONLY +#define TSCH_JOIN_MY_PANID_ONLY TSCH_CONF_JOIN_MY_PANID_ONLY +#else +#define TSCH_JOIN_MY_PANID_ONLY 1 +#endif + +/* The radio polling frequency (in Hz) during association process */ +#ifdef TSCH_CONF_ASSOCIATION_POLL_FREQUENCY +#define TSCH_ASSOCIATION_POLL_FREQUENCY TSCH_CONF_ASSOCIATION_POLL_FREQUENCY +#else +#define TSCH_ASSOCIATION_POLL_FREQUENCY 100 +#endif + +/* When associating, check ASN against our own uptime (time in minutes).. + * Useful to force joining only with nodes started roughly at the same time. + * Set to the max number of minutes acceptable. */ +#ifdef TSCH_CONF_CHECK_TIME_AT_ASSOCIATION +#define TSCH_CHECK_TIME_AT_ASSOCIATION TSCH_CONF_CHECK_TIME_AT_ASSOCIATION +#else +#define TSCH_CHECK_TIME_AT_ASSOCIATION 0 +#endif + +/* By default: initialize schedule from EB when associating, using the + * slotframe and links Information Element */ +#ifdef TSCH_CONF_INIT_SCHEDULE_FROM_EB +#define TSCH_INIT_SCHEDULE_FROM_EB TSCH_CONF_INIT_SCHEDULE_FROM_EB +#else +#define TSCH_INIT_SCHEDULE_FROM_EB 1 +#endif + +/* How long to scan each channel in the scanning phase */ +#ifdef TSCH_CONF_CHANNEL_SCAN_DURATION +#define TSCH_CHANNEL_SCAN_DURATION TSCH_CONF_CHANNEL_SCAN_DURATION +#else +#define TSCH_CHANNEL_SCAN_DURATION CLOCK_SECOND +#endif + +/* TSCH EB: include timeslot timing Information Element? */ +#ifdef TSCH_PACKET_CONF_EB_WITH_TIMESLOT_TIMING +#define TSCH_PACKET_EB_WITH_TIMESLOT_TIMING TSCH_PACKET_CONF_EB_WITH_TIMESLOT_TIMING +#else +#define TSCH_PACKET_EB_WITH_TIMESLOT_TIMING 0 +#endif + +/* TSCH EB: include hopping sequence Information Element? */ +#ifdef TSCH_PACKET_CONF_EB_WITH_HOPPING_SEQUENCE +#define TSCH_PACKET_EB_WITH_HOPPING_SEQUENCE TSCH_PACKET_CONF_EB_WITH_HOPPING_SEQUENCE +#else +#define TSCH_PACKET_EB_WITH_HOPPING_SEQUENCE 0 +#endif + +/* TSCH EB: include slotframe and link Information Element? */ +#ifdef TSCH_PACKET_CONF_EB_WITH_SLOTFRAME_AND_LINK +#define TSCH_PACKET_EB_WITH_SLOTFRAME_AND_LINK TSCH_PACKET_CONF_EB_WITH_SLOTFRAME_AND_LINK +#else +#define TSCH_PACKET_EB_WITH_SLOTFRAME_AND_LINK 0 +#endif + +/******** Configuration: queues *******/ + +/* Size of the ring buffer storing dequeued outgoing packets (only an array of pointers). + * Must be power of two, and greater or equal to QUEUEBUF_NUM */ +#ifdef TSCH_CONF_DEQUEUED_ARRAY_SIZE +#define TSCH_DEQUEUED_ARRAY_SIZE TSCH_CONF_DEQUEUED_ARRAY_SIZE +#else +/* By default, round QUEUEBUF_CONF_NUM to next power of two + * (in the range [4;256]) */ +#if QUEUEBUF_CONF_NUM <= 4 +#define TSCH_DEQUEUED_ARRAY_SIZE 4 +#elif QUEUEBUF_CONF_NUM <= 8 +#define TSCH_DEQUEUED_ARRAY_SIZE 8 +#elif QUEUEBUF_CONF_NUM <= 16 +#define TSCH_DEQUEUED_ARRAY_SIZE 16 +#elif QUEUEBUF_CONF_NUM <= 32 +#define TSCH_DEQUEUED_ARRAY_SIZE 32 +#elif QUEUEBUF_CONF_NUM <= 64 +#define TSCH_DEQUEUED_ARRAY_SIZE 64 +#elif QUEUEBUF_CONF_NUM <= 128 +#define TSCH_DEQUEUED_ARRAY_SIZE 128 +#else +#define TSCH_DEQUEUED_ARRAY_SIZE 256 +#endif +#endif + +/* Size of the ring buffer storing incoming packets. + * Must be power of two */ +#ifdef TSCH_CONF_MAX_INCOMING_PACKETS +#define TSCH_MAX_INCOMING_PACKETS TSCH_CONF_MAX_INCOMING_PACKETS +#else +#define TSCH_MAX_INCOMING_PACKETS 4 +#endif + +/* The maximum number of outgoing packets towards each neighbor + * Must be power of two to enable atomic ringbuf operations. + * Note: the total number of outgoing packets in the system (for + * all neighbors) is defined via QUEUEBUF_CONF_NUM */ +#ifdef TSCH_QUEUE_CONF_NUM_PER_NEIGHBOR +#define TSCH_QUEUE_NUM_PER_NEIGHBOR TSCH_QUEUE_CONF_NUM_PER_NEIGHBOR +#else +/* By default, round QUEUEBUF_CONF_NUM to next power of two + * (in the range [4;256]) */ +#if QUEUEBUF_CONF_NUM <= 4 +#define TSCH_QUEUE_NUM_PER_NEIGHBOR 4 +#elif QUEUEBUF_CONF_NUM <= 8 +#define TSCH_QUEUE_NUM_PER_NEIGHBOR 8 +#elif QUEUEBUF_CONF_NUM <= 16 +#define TSCH_QUEUE_NUM_PER_NEIGHBOR 16 +#elif QUEUEBUF_CONF_NUM <= 32 +#define TSCH_QUEUE_NUM_PER_NEIGHBOR 32 +#elif QUEUEBUF_CONF_NUM <= 64 +#define TSCH_QUEUE_NUM_PER_NEIGHBOR 64 +#elif QUEUEBUF_CONF_NUM <= 128 +#define TSCH_QUEUE_NUM_PER_NEIGHBOR 128 +#else +#define TSCH_QUEUE_NUM_PER_NEIGHBOR 256 +#endif +#endif + +/* The number of neighbor queues. There are two queues allocated at all times: + * one for EBs, one for broadcasts. Other queues are for unicast to neighbors */ +#ifdef TSCH_QUEUE_CONF_MAX_NEIGHBOR_QUEUES +#define TSCH_QUEUE_MAX_NEIGHBOR_QUEUES TSCH_QUEUE_CONF_MAX_NEIGHBOR_QUEUES +#else +#define TSCH_QUEUE_MAX_NEIGHBOR_QUEUES ((NBR_TABLE_CONF_MAX_NEIGHBORS) + 2) +#endif + +/******** Configuration: scheduling *******/ + +/* Initializes TSCH with a 6TiSCH minimal schedule */ +#ifdef TSCH_SCHEDULE_CONF_WITH_6TISCH_MINIMAL +#define TSCH_SCHEDULE_WITH_6TISCH_MINIMAL TSCH_SCHEDULE_CONF_WITH_6TISCH_MINIMAL +#else +#define TSCH_SCHEDULE_WITH_6TISCH_MINIMAL (!(BUILD_WITH_ORCHESTRA)) +#endif + +/* 6TiSCH Minimal schedule slotframe length */ +#ifdef TSCH_SCHEDULE_CONF_DEFAULT_LENGTH +#define TSCH_SCHEDULE_DEFAULT_LENGTH TSCH_SCHEDULE_CONF_DEFAULT_LENGTH +#else +#define TSCH_SCHEDULE_DEFAULT_LENGTH 7 +#endif + +/* Max number of TSCH slotframes */ +#ifdef TSCH_SCHEDULE_CONF_MAX_SLOTFRAMES +#define TSCH_SCHEDULE_MAX_SLOTFRAMES TSCH_SCHEDULE_CONF_MAX_SLOTFRAMES +#else +#define TSCH_SCHEDULE_MAX_SLOTFRAMES 4 +#endif + +/* Max number of links */ +#ifdef TSCH_SCHEDULE_CONF_MAX_LINKS +#define TSCH_SCHEDULE_MAX_LINKS TSCH_SCHEDULE_CONF_MAX_LINKS +#else +#define TSCH_SCHEDULE_MAX_LINKS 32 +#endif + +/* To include Sixtop Implementation */ +#ifdef TSCH_CONF_WITH_SIXTOP +#define TSCH_WITH_SIXTOP TSCH_CONF_WITH_SIXTOP +#else +#define TSCH_WITH_SIXTOP 0 #endif /* A custom feature allowing upper layers to assign packets to @@ -175,12 +353,44 @@ #define TSCH_WITH_LINK_SELECTOR (BUILD_WITH_ORCHESTRA) #endif /* TSCH_CONF_WITH_LINK_SELECTOR */ -/* Estimate the drift of the time-source neighbor and compensate for it? */ -#ifdef TSCH_CONF_ADAPTIVE_TIMESYNC -#define TSCH_ADAPTIVE_TIMESYNC TSCH_CONF_ADAPTIVE_TIMESYNC +/******** Configuration: CSMA *******/ + +/* TSCH CSMA-CA parameters, see IEEE 802.15.4e-2012 */ +/* Min backoff exponent */ +#ifdef TSCH_CONF_MAC_MIN_BE +#define TSCH_MAC_MIN_BE TSCH_CONF_MAC_MIN_BE #else -#define TSCH_ADAPTIVE_TIMESYNC 1 +#define TSCH_MAC_MIN_BE 1 +#endif +/* Max backoff exponent */ +#ifdef TSCH_CONF_MAC_MAX_BE +#define TSCH_MAC_MAX_BE TSCH_CONF_MAC_MAX_BE +#else +#define TSCH_MAC_MAX_BE 5 #endif +/* Max number of re-transmissions */ +#ifdef TSCH_CONF_MAC_MAX_FRAME_RETRIES +#define TSCH_MAC_MAX_FRAME_RETRIES TSCH_CONF_MAC_MAX_FRAME_RETRIES +#else +#define TSCH_MAC_MAX_FRAME_RETRIES 7 +#endif + +/* Include source address in ACK? */ +#ifdef TSCH_PACKET_CONF_EACK_WITH_SRC_ADDR +#define TSCH_PACKET_EACK_WITH_SRC_ADDR TSCH_PACKET_CONF_EACK_WITH_SRC_ADDR +#else +#define TSCH_PACKET_EACK_WITH_SRC_ADDR 0 +#endif + +/* Include destination address in ACK? */ +#ifdef TSCH_PACKET_CONF_EACK_WITH_DEST_ADDR +#define TSCH_PACKET_EACK_WITH_DEST_ADDR TSCH_PACKET_CONF_EACK_WITH_DEST_ADDR +#else +#define TSCH_PACKET_EACK_WITH_DEST_ADDR 1 /* Include destination address +by default, useful in case of duplicate seqno */ +#endif + +/******** Configuration: hardware-specific settings *******/ /* HW frame filtering enabled */ #ifdef TSCH_CONF_HW_FRAME_FILTERING @@ -196,12 +406,17 @@ #define TSCH_RADIO_ON_DURING_TIMESLOT 0 #endif -/* How long to scan each channel in the scanning phase */ -#ifdef TSCH_CONF_CHANNEL_SCAN_DURATION -#define TSCH_CHANNEL_SCAN_DURATION TSCH_CONF_CHANNEL_SCAN_DURATION -#else -#define TSCH_CHANNEL_SCAN_DURATION CLOCK_SECOND -#endif + + +/* Timeslot timing */ +#ifndef TSCH_CONF_DEFAULT_TIMESLOT_LENGTH +#define TSCH_CONF_DEFAULT_TIMESLOT_LENGTH 10000 +#endif /* TSCH_CONF_DEFAULT_TIMESLOT_LENGTH */ + +/* Configurable Rx guard time is micro-seconds */ +#ifndef TSCH_CONF_RX_WAIT +#define TSCH_CONF_RX_WAIT 2200 +#endif /* TSCH_CONF_RX_WAIT */ #endif /* __TSCH_CONF_H__ */ /** @} */ diff --git a/os/net/mac/tsch/tsch-const.h b/os/net/mac/tsch/tsch-const.h new file mode 100644 index 0000000000000000000000000000000000000000..81ca7ffa8306b5a9ad3a74ec7b392f6c778ffdf3 --- /dev/null +++ b/os/net/mac/tsch/tsch-const.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2015, SICS Swedish ICT. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** +* \addtogroup tsch +* @{ + * \file + * TSCH constants + * \author + * Simon Duquennoy <simonduq@sics.se> + */ + +#ifndef __TSCH_CONST_H__ +#define __TSCH_CONST_H__ + +/********** Includes **********/ +#include "net/packetbuf.h" +#include "net/mac/tsch/tsch-conf.h" /* Required for timestlot timing consts */ + +/********** Constants **********/ + +/* Link options */ +#define LINK_OPTION_TX 1 +#define LINK_OPTION_RX 2 +#define LINK_OPTION_SHARED 4 +#define LINK_OPTION_TIME_KEEPING 8 + +/* Default IEEE 802.15.4e hopping sequences, obtained from https://gist.github.com/twatteyne/2e22ee3c1a802b685695 */ +/* 16 channels, sequence length 16 */ +#define TSCH_HOPPING_SEQUENCE_16_16 (uint8_t[]){ 16, 17, 23, 18, 26, 15, 25, 22, 19, 11, 12, 13, 24, 14, 20, 21 } +/* 4 channels, sequence length 16 */ +#define TSCH_HOPPING_SEQUENCE_4_16 (uint8_t[]){ 20, 26, 25, 26, 15, 15, 25, 20, 26, 15, 26, 25, 20, 15, 20, 25 } +/* 4 channels, sequence length 4 */ +#define TSCH_HOPPING_SEQUENCE_4_4 (uint8_t[]){ 15, 25, 26, 20 } +/* 2 channels, sequence length 2 */ +#define TSCH_HOPPING_SEQUENCE_2_2 (uint8_t[]){ 20, 25 } +/* 1 channel, sequence length 1 */ +#define TSCH_HOPPING_SEQUENCE_1_1 (uint8_t[]){ 20 } + +/* Max TSCH packet lenght */ +#define TSCH_PACKET_MAX_LEN MIN(127, PACKETBUF_SIZE) + +/* The jitter to remove in ticks. + * This should be the sum of measurement errors on Tx and Rx nodes. + * */ +#define TSCH_TIMESYNC_MEASUREMENT_ERROR US_TO_RTIMERTICKS(32) + +/* The approximate number of slots per second */ +#define TSCH_SLOTS_PER_SECOND (1000000 / TSCH_DEFAULT_TS_TIMESLOT_LENGTH) + +/* Calculate packet tx/rx duration in rtimer ticks based on sent + * packet len in bytes with 802.15.4 250kbps data rate. + * One byte = 32us. Add two bytes for CRC and one for len field */ +#define TSCH_PACKET_DURATION(len) US_TO_RTIMERTICKS(32 * ((len) + 3)) + +/* Convert rtimer ticks to clock and vice versa */ +#define TSCH_CLOCK_TO_TICKS(c) (((c) * RTIMER_SECOND) / CLOCK_SECOND) +#define TSCH_CLOCK_TO_SLOTS(c, timeslot_length) (TSCH_CLOCK_TO_TICKS(c) / timeslot_length) + +/* The default timeslot timing in the standard is a guard time of + * 2200 us, a Tx offset of 2120 us and a Rx offset of 1120 us. + * As a result, the listening device has a guard time not centered + * on the expected Tx time. This is to be fixed in the next iteration + * of the standard. This can be enabled with: + * #define TSCH_DEFAULT_TS_TX_OFFSET 2120 + * #define TSCH_DEFAULT_TS_RX_OFFSET 1120 + * #define TSCH_DEFAULT_TS_RX_WAIT 2200 + * + * Instead, we align the Rx guard time on expected Tx time. The Rx + * guard time is user-configurable with TSCH_CONF_RX_WAIT. + + * (TS_TX_OFFSET - (TS_RX_WAIT / 2)) instead */ + +#if TSCH_CONF_DEFAULT_TIMESLOT_LENGTH == 10000 +/* Default timeslot timing as per IEEE 802.15.4e */ + +#define TSCH_DEFAULT_TS_CCA_OFFSET 1800 +#define TSCH_DEFAULT_TS_CCA 128 +#define TSCH_DEFAULT_TS_TX_OFFSET 2120 +#define TSCH_DEFAULT_TS_RX_OFFSET (TSCH_DEFAULT_TS_TX_OFFSET - (TSCH_CONF_RX_WAIT / 2)) +#define TSCH_DEFAULT_TS_RX_ACK_DELAY 800 +#define TSCH_DEFAULT_TS_TX_ACK_DELAY 1000 +#define TSCH_DEFAULT_TS_RX_WAIT TSCH_CONF_RX_WAIT +#define TSCH_DEFAULT_TS_ACK_WAIT 400 +#define TSCH_DEFAULT_TS_RX_TX 192 +#define TSCH_DEFAULT_TS_MAX_ACK 2400 +#define TSCH_DEFAULT_TS_MAX_TX 4256 +#define TSCH_DEFAULT_TS_TIMESLOT_LENGTH 10000 + +#elif TSCH_CONF_DEFAULT_TIMESLOT_LENGTH == 15000 +/* Default timeslot timing for platforms requiring 15ms slots */ + +#define TSCH_DEFAULT_TS_CCA_OFFSET 1800 +#define TSCH_DEFAULT_TS_CCA 128 +#define TSCH_DEFAULT_TS_TX_OFFSET 4000 +#define TSCH_DEFAULT_TS_RX_OFFSET (TSCH_DEFAULT_TS_TX_OFFSET - (TSCH_CONF_RX_WAIT / 2)) +#define TSCH_DEFAULT_TS_RX_ACK_DELAY 3600 +#define TSCH_DEFAULT_TS_TX_ACK_DELAY 4000 +#define TSCH_DEFAULT_TS_RX_WAIT TSCH_CONF_RX_WAIT +#define TSCH_DEFAULT_TS_ACK_WAIT 800 +#define TSCH_DEFAULT_TS_RX_TX 2072 +#define TSCH_DEFAULT_TS_MAX_ACK 2400 +#define TSCH_DEFAULT_TS_MAX_TX 4256 +#define TSCH_DEFAULT_TS_TIMESLOT_LENGTH 15000 + +#elif TSCH_CONF_DEFAULT_TIMESLOT_LENGTH == 65000U +/* 65ms timeslot, i.e. nearly the max length allowed by standard (16-bit unsigned in micro-seconds). + * Useful for running link-layer security on sky in Cooja, where only S/W security is supported. + * Note: this slot timing would require a total of 120ms. If a slot overlaps with the next active slot, + * the latter will be skipped. + * This configuration is mostly a work-around to test link-layer security in Cooja, it is recommended + * to use it with a 6TiSCH minimal schedule of length >= 2. */ + +#define TSCH_DEFAULT_TS_CCA_OFFSET 1800 +#define TSCH_DEFAULT_TS_CCA 128 +#define TSCH_DEFAULT_TS_TX_OFFSET 52000 +#define TSCH_DEFAULT_TS_RX_OFFSET (TSCH_DEFAULT_TS_TX_OFFSET - (TSCH_CONF_RX_WAIT / 2)) +#define TSCH_DEFAULT_TS_RX_ACK_DELAY 58600 +#define TSCH_DEFAULT_TS_TX_ACK_DELAY 59000 +#define TSCH_DEFAULT_TS_RX_WAIT TSCH_CONF_RX_WAIT +#define TSCH_DEFAULT_TS_ACK_WAIT 800 +#define TSCH_DEFAULT_TS_RX_TX 2072 +#define TSCH_DEFAULT_TS_MAX_ACK 2400 +#define TSCH_DEFAULT_TS_MAX_TX 4256 +#define TSCH_DEFAULT_TS_TIMESLOT_LENGTH 65000 + +#else +#error "TSCH: Unsupported default timeslot length" +#endif + +#endif /* __TSCH_CONST_H__ */ +/** @} */ diff --git a/os/net/mac/tsch/tsch-log.c b/os/net/mac/tsch/tsch-log.c index 9235d9d7d44ab5e440a227f4ca24ce7fd431423d..d27dac0647891ad37e5bf1857d7c6d88197ddc9d 100644 --- a/os/net/mac/tsch/tsch-log.c +++ b/os/net/mac/tsch/tsch-log.c @@ -48,12 +48,6 @@ #include "contiki.h" #include <stdio.h> #include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-queue.h" -#include "net/mac/tsch/tsch-private.h" -#include "net/mac/tsch/tsch-log.h" -#include "net/mac/tsch/tsch-packet.h" -#include "net/mac/tsch/tsch-schedule.h" -#include "net/mac/tsch/tsch-slot-operation.h" #include "lib/ringbufindex.h" #include "sys/log.h" @@ -85,10 +79,10 @@ tsch_log_process_pending(void) while((log_index = ringbufindex_peek_get(&log_ringbuf)) != -1) { struct tsch_log_t *log = &log_array[log_index]; if(log->link == NULL) { - printf("[INFO: TSCH-LOG ] {asn-%x.%lx link-NULL} ", log->asn.ms1b, log->asn.ls4b); + printf("[INFO: TSCH-LOG ] {asn %02x.%08lx link-NULL} ", log->asn.ms1b, log->asn.ls4b); } else { struct tsch_slotframe *sf = tsch_schedule_get_slotframe_by_handle(log->link->slotframe_handle); - printf("[INFO: TSCH-LOG ] {asn-%x.%lx link-%u-%u-%u-%u ch-%u} ", + printf("[INFO: TSCH-LOG ] {asn %02x.%08lx link %2u %3u %3u %2u ch %2u} ", log->asn.ms1b, log->asn.ls4b, log->link->slotframe_handle, sf ? sf->size.val : 0, log->link->timeslot, log->link->channel_offset, tsch_calculate_channel(&log->asn, log->link->channel_offset)); @@ -100,10 +94,10 @@ tsch_log_process_pending(void) log_lladdr_compact(&linkaddr_node_addr); printf("->"); log_lladdr_compact(&log->tx.dest); - printf(", len %u, seq %u, st %d %d", + printf(", len %3u, seq %3u, st %d %2d", log->tx.datalen, log->tx.seqno, log->tx.mac_tx_status, log->tx.num_tx); if(log->tx.drift_used) { - printf(", dr %d", log->tx.drift); + printf(", dr %3d", log->tx.drift); } printf("\n"); break; @@ -113,12 +107,14 @@ tsch_log_process_pending(void) log_lladdr_compact(&log->rx.src); printf("->"); log_lladdr_compact(log->rx.is_unicast ? &linkaddr_node_addr : NULL); - printf(", len %u, seq %u", + printf(", len %3u, seq %3u", log->rx.datalen, log->rx.seqno); + printf(", edr %3d", (int)log->rx.estimated_drift); if(log->rx.drift_used) { - printf(", dr %d", log->rx.drift); + printf(", dr %3d\n", log->rx.drift); + } else { + printf("\n"); } - printf(", edr %d\n", (int)log->rx.estimated_drift); break; case tsch_log_message: printf("%s\n", log->message); diff --git a/os/net/mac/tsch/tsch-log.h b/os/net/mac/tsch/tsch-log.h index 06888e24f7ba24b1ed153947372ad1ce722073bf..468eff86915bc2e13a2ab03a7018eed87c1734c3 100644 --- a/os/net/mac/tsch/tsch-log.h +++ b/os/net/mac/tsch/tsch-log.h @@ -33,6 +33,8 @@ /** * \addtogroup tsch * @{ + * \file + * TSCH per-slot logging */ #ifndef __TSCH_LOG_H__ @@ -42,7 +44,6 @@ #include "contiki.h" #include "sys/rtimer.h" -#include "net/mac/tsch/tsch-private.h" /******** Configuration *******/ @@ -71,7 +72,7 @@ /************ Types ***********/ -/* Structure for a log. Union of different types of logs */ +/** \brief Structure for a log. Union of different types of logs */ struct tsch_log_t { enum { tsch_log_tx, tsch_log_rx, @@ -108,21 +109,31 @@ struct tsch_log_t { /********** Functions *********/ -/* Prepare addition of a new log. - * Returns pointer to log structure if success, NULL otherwise */ +/** + * \brief Prepare addition of a new log. + * \return A pointer to log structure if success, NULL otherwise + */ struct tsch_log_t *tsch_log_prepare_add(void); -/* Actually add the previously prepared log */ +/** + * \brief Actually add the previously prepared log + */ void tsch_log_commit(void); -/* Initialize log module */ +/** + * \brief Initialize log module + */ void tsch_log_init(void); -/* Process pending log messages */ +/** + * \brief Process pending log messages + */ void tsch_log_process_pending(void); -/* Stop logging module */ +/** + * \brief Stop logging module + */ void tsch_log_stop(void); /************ Macros **********/ -/* Use this macro to add a log to the queue (will be printed out +/** \brief Use this macro to add a log to the queue (will be printed out * later, after leaving interrupt context) */ #define TSCH_LOG_ADD(log_type, init_code) do { \ struct tsch_log_t *log = tsch_log_prepare_add(); \ diff --git a/os/net/mac/tsch/tsch-packet.c b/os/net/mac/tsch/tsch-packet.c index 2db212dacf4691eb74fe0c151533ff4bb3668c34..64f03b588c510366660ef12e0f4f9085c3ea56d6 100644 --- a/os/net/mac/tsch/tsch-packet.c +++ b/os/net/mac/tsch/tsch-packet.c @@ -46,10 +46,6 @@ #include "contiki.h" #include "net/packetbuf.h" #include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-packet.h" -#include "net/mac/tsch/tsch-private.h" -#include "net/mac/tsch/tsch-schedule.h" -#include "net/mac/tsch/tsch-security.h" #include "net/mac/framer/frame802154.h" #include "net/mac/framer/framer-802154.h" #include "net/netstack.h" @@ -394,8 +390,7 @@ tsch_packet_update_eb(uint8_t *buf, int buf_size, uint8_t tsch_sync_ie_offset) struct ieee802154_ies ies; ies.ie_asn = tsch_current_asn; ies.ie_join_priority = tsch_join_priority; - frame80215e_create_ie_tsch_synchronization(buf+tsch_sync_ie_offset, buf_size-tsch_sync_ie_offset, &ies); - return 1; + return frame80215e_create_ie_tsch_synchronization(buf+tsch_sync_ie_offset, buf_size-tsch_sync_ie_offset, &ies) != -1; } /*---------------------------------------------------------------------------*/ /* Parse a IEEE 802.15.4e TSCH Enhanced Beacon (EB) */ diff --git a/os/net/mac/tsch/tsch-packet.h b/os/net/mac/tsch/tsch-packet.h index 717e0fddacb4e5729c55b46a6e9413ea2787c4b3..6b05d665332c9b32b41bd42bbf32cf28e818e869 100644 --- a/os/net/mac/tsch/tsch-packet.h +++ b/os/net/mac/tsch/tsch-packet.h @@ -33,6 +33,8 @@ /** * \addtogroup tsch * @{ + * \file + * TSCH packet parsing and creation. EBs and EACKs. */ #ifndef __TSCH_PACKET_H__ @@ -41,68 +43,61 @@ /********** Includes **********/ #include "contiki.h" -#include "net/packetbuf.h" -#include "net/mac/tsch/tsch-private.h" #include "net/mac/framer/frame802154.h" #include "net/mac/framer/frame802154e-ie.h" -/******** Configuration *******/ - -/* TSCH EB: include timeslot timing Information Element? */ -#ifdef TSCH_PACKET_CONF_EB_WITH_TIMESLOT_TIMING -#define TSCH_PACKET_EB_WITH_TIMESLOT_TIMING TSCH_PACKET_CONF_EB_WITH_TIMESLOT_TIMING -#else -#define TSCH_PACKET_EB_WITH_TIMESLOT_TIMING 0 -#endif - -/* TSCH EB: include hopping sequence Information Element? */ -#ifdef TSCH_PACKET_CONF_EB_WITH_HOPPING_SEQUENCE -#define TSCH_PACKET_EB_WITH_HOPPING_SEQUENCE TSCH_PACKET_CONF_EB_WITH_HOPPING_SEQUENCE -#else -#define TSCH_PACKET_EB_WITH_HOPPING_SEQUENCE 0 -#endif - -/* TSCH EB: include slotframe and link Information Element? */ -#ifdef TSCH_PACKET_CONF_EB_WITH_SLOTFRAME_AND_LINK -#define TSCH_PACKET_EB_WITH_SLOTFRAME_AND_LINK TSCH_PACKET_CONF_EB_WITH_SLOTFRAME_AND_LINK -#else -#define TSCH_PACKET_EB_WITH_SLOTFRAME_AND_LINK 0 -#endif - -/* Include source address in ACK? */ -#ifdef TSCH_PACKET_CONF_EACK_WITH_SRC_ADDR -#define TSCH_PACKET_EACK_WITH_SRC_ADDR TSCH_PACKET_CONF_EACK_WITH_SRC_ADDR -#else -#define TSCH_PACKET_EACK_WITH_SRC_ADDR 0 -#endif - -/* Include destination address in ACK? */ -#ifdef TSCH_PACKET_CONF_EACK_WITH_DEST_ADDR -#define TSCH_PACKET_EACK_WITH_DEST_ADDR TSCH_PACKET_CONF_EACK_WITH_DEST_ADDR -#else -#define TSCH_PACKET_EACK_WITH_DEST_ADDR 1 /* Include destination address -by default, useful in case of duplicate seqno */ -#endif - -/********** Constants *********/ - -/* Max TSCH packet lenght */ -#define TSCH_PACKET_MAX_LEN MIN(127,PACKETBUF_SIZE) - /********** Functions *********/ -/* Construct enhanced ACK packet and return ACK length */ +/** + * \brief Construct Enhanced ACK packet + * \param buf The buffer where to build the EACK + * \param buf_size The buffer size + * \param dest_addr The link-layer address of the neighbor we are ACKing + * \param seqno The sequence number we are ACKing + * \param drift The time offset in usec measured at Rx of the packer we are ACKing + * \param nack Value of the NACK bit + * \return The length of the packet that was created. -1 if failure. + */ int tsch_packet_create_eack(uint8_t *buf, uint16_t buf_size, const linkaddr_t *dest_addr, uint8_t seqno, int16_t drift, int nack); -/* Parse enhanced ACK packet, extract drift and nack */ +/** + * \brief Parse enhanced ACK packet + * \param buf The buffer where to parse the EACK from + * \param buf_size The buffer size + * \param seqno The sequence number we are expecting + * \param frame The frame structure where to store parsed fields + * \param ies The IE structure where to store parsed IEs + * \param hdr_len A pointer where to store the length of the parsed header + * \return 1 if the EACK is correct and acknowledges the specified frame, 0 otherwise + */ int tsch_packet_parse_eack(const uint8_t *buf, int buf_size, uint8_t seqno, frame802154_t *frame, struct ieee802154_ies *ies, uint8_t *hdr_len); -/* Create an EB packet */ +/** + * \brief Create an EB packet directly in packetbuf + * \param hdr_len A pointer where to store the length of the created header + * \param tsch_sync_ie_ptr A pointer where to store the address of the TSCH synchronization IE + * \return The total length of the EB + */ int tsch_packet_create_eb(uint8_t *hdr_len, uint8_t *tsch_sync_ie_ptr); -/* Update ASN in EB packet */ +/** + * \brief Update ASN in EB packet + * \param buf The buffer that contains the EB + * \param buf_size The buffer size + * \param tsch_sync_ie_offset The offset of the TSCH synchronization IE, in which the ASN is to be written + * \return 1 if success, 0 otherwise + */ int tsch_packet_update_eb(uint8_t *buf, int buf_size, uint8_t tsch_sync_ie_offset); -/* Parse EB and extract ASN and join priority */ +/** + * \brief Parse EB + * \param buf The buffer where to parse the EB from + * \param buf_size The buffer sizecting + * \param frame The frame structure where to store parsed fields + * \param ies The IE structure where to store parsed IEs + * \param hdrlen A pointer where to store the length of the parsed header + * \param frame_without_mic When set, the security MIC will not be parsed + * \return The length of the parsed EB + */ int tsch_packet_parse_eb(const uint8_t *buf, int buf_size, frame802154_t *frame, struct ieee802154_ies *ies, uint8_t *hdrlen, int frame_without_mic); diff --git a/os/net/mac/tsch/tsch-private.h b/os/net/mac/tsch/tsch-private.h deleted file mode 100644 index ec114813eb6f38a284b2bb34c2cf2654576f3ccd..0000000000000000000000000000000000000000 --- a/os/net/mac/tsch/tsch-private.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2014, SICS Swedish ICT. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ - -/** - * \file - * Private TSCH definitions - * (meant for use by TSCH implementation files only) - * \author - * Simon Duquennoy <simonduq@sics.se> - * Beshr Al Nahas <beshr@sics.se> - */ - -/** - * \addtogroup tsch - * @{ -*/ - -#ifndef __TSCH_PRIVATE_H__ -#define __TSCH_PRIVATE_H__ - -/********** Includes **********/ - -#include "contiki.h" -#include "net/linkaddr.h" -#include "net/mac/tsch/tsch-asn.h" -#include "net/mac/tsch/tsch-conf.h" -#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 -#include "lib/simEnvChange.h" -#include "sys/cooja_mt.h" -#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */ - -/************ Types ***********/ - -/* TSCH timeslot timing elements. Used to index timeslot timing - * of different units, such as rtimer tick or micro-second */ -enum tsch_timeslot_timing_elements { - tsch_ts_cca_offset, - tsch_ts_cca, - tsch_ts_tx_offset, - tsch_ts_rx_offset, - tsch_ts_rx_ack_delay, - tsch_ts_tx_ack_delay, - tsch_ts_rx_wait, - tsch_ts_ack_wait, - tsch_ts_rx_tx, - tsch_ts_max_ack, - tsch_ts_max_tx, - tsch_ts_timeslot_length, - tsch_ts_elements_count, /* Not a timing element */ -}; - -/***** External Variables *****/ - -/* 802.15.4 broadcast MAC address */ -extern const linkaddr_t tsch_broadcast_address; -/* The address we use to identify EB queue */ -extern const linkaddr_t tsch_eb_address; -/* The current Absolute Slot Number (ASN) */ -extern struct tsch_asn_t tsch_current_asn; -extern uint8_t tsch_join_priority; -extern struct tsch_link *current_link; -/* TSCH channel hopping sequence */ -extern uint8_t tsch_hopping_sequence[TSCH_HOPPING_SEQUENCE_MAX_LEN]; -extern struct tsch_asn_divisor_t tsch_hopping_sequence_length; -/* TSCH timeslot timing (in rtimer ticks) */ -extern rtimer_clock_t tsch_timing[tsch_ts_elements_count]; -/* Statistics on the current session */ -unsigned long tx_count; -unsigned long rx_count; -unsigned long sync_count; - -/* TSCH processes */ -PROCESS_NAME(tsch_process); -PROCESS_NAME(tsch_send_eb_process); -PROCESS_NAME(tsch_pending_events_process); - -/********** Functions *********/ - -/* Set TSCH to send a keepalive message after TSCH_KEEPALIVE_TIMEOUT */ -void tsch_schedule_keepalive(void); -/* Set TSCH to send a keepalive message immediately */ -void tsch_schedule_keepalive_immediately(void); -/* Leave the TSCH network */ -void tsch_disassociate(void); - -/************ Macros **********/ - -/* Calculate packet tx/rx duration in rtimer ticks based on sent - * packet len in bytes with 802.15.4 250kbps data rate. - * One byte = 32us. Add two bytes for CRC and one for len field */ -#define TSCH_PACKET_DURATION(len) US_TO_RTIMERTICKS(32 * ((len) + 3)) - -/* Convert rtimer ticks to clock and vice versa */ -#define TSCH_CLOCK_TO_TICKS(c) (((c) * RTIMER_SECOND) / CLOCK_SECOND) -#define TSCH_CLOCK_TO_SLOTS(c, timeslot_length) (TSCH_CLOCK_TO_TICKS(c) / timeslot_length) - -/* Wait for a condition with timeout t0+offset. */ -#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 -#define BUSYWAIT_UNTIL_ABS(cond, t0, offset) \ - while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (offset))) { \ - simProcessRunValue = 1; \ - cooja_mt_yield(); \ - }; -#else -#define BUSYWAIT_UNTIL_ABS(cond, t0, offset) \ - while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (offset))) ; -#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */ -#endif /* __TSCH_PRIVATE_H__ */ -/** @} */ diff --git a/os/net/mac/tsch/tsch-queue.c b/os/net/mac/tsch/tsch-queue.c index 388953a602c3b9b834c2de872d15406022c93ad8..4ef5130fb5fb3bf46f054f2b6727b0fc401beebd 100644 --- a/os/net/mac/tsch/tsch-queue.c +++ b/os/net/mac/tsch/tsch-queue.c @@ -53,11 +53,6 @@ #include "lib/random.h" #include "net/queuebuf.h" #include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-private.h" -#include "net/mac/tsch/tsch-queue.h" -#include "net/mac/tsch/tsch-schedule.h" -#include "net/mac/tsch/tsch-slot-operation.h" -#include "net/mac/tsch/tsch-log.h" #include <string.h> /* Log configuration */ @@ -230,7 +225,8 @@ tsch_queue_remove_nbr(struct tsch_neighbor *n) /*---------------------------------------------------------------------------*/ /* Add packet to neighbor queue. Use same lockfree implementation as ringbuf.c (put is atomic) */ struct tsch_packet * -tsch_queue_add_packet(const linkaddr_t *addr, mac_callback_t sent, void *ptr) +tsch_queue_add_packet(const linkaddr_t *addr, uint8_t max_transmissions, + mac_callback_t sent, void *ptr) { struct tsch_neighbor *n = NULL; int16_t put_index = -1; @@ -252,6 +248,7 @@ tsch_queue_add_packet(const linkaddr_t *addr, mac_callback_t sent, void *ptr) p->ptr = ptr; p->ret = MAC_TX_DEFERRED; p->transmissions = 0; + p->max_transmissions = max_transmissions; /* Add to ringbuf (actual add committed through atomic operation) */ n->tx_array[put_index] = p; ringbufindex_put(&n->tx_ringbuf); @@ -342,7 +339,7 @@ tsch_queue_packet_sent(struct tsch_neighbor *n, struct tsch_packet *p, } } else { /* Failed transmission */ - if(p->transmissions >= TSCH_MAC_MAX_FRAME_RETRIES + 1) { + if(p->transmissions >= p->max_transmissions) { /* Drop packet */ tsch_queue_remove_packet_from_queue(n); in_queue = 0; diff --git a/os/net/mac/tsch/tsch-queue.h b/os/net/mac/tsch/tsch-queue.h index 037461e7de0cebfb2fe214efda23bab3ed65b3e3..b7edcf300727ee59bf0b866d4d1eff2e53a1c940 100644 --- a/os/net/mac/tsch/tsch-queue.h +++ b/os/net/mac/tsch/tsch-queue.h @@ -33,6 +33,8 @@ /** * \addtogroup tsch * @{ + * \file + * TSCH queues */ #ifndef __TSCH_QUEUE_H__ @@ -43,122 +45,8 @@ #include "contiki.h" #include "lib/ringbufindex.h" #include "net/linkaddr.h" -#include "net/mac/tsch/tsch-schedule.h" #include "net/mac/mac.h" -/******** Configuration *******/ - -/* The maximum number of outgoing packets towards each neighbor - * Must be power of two to enable atomic ringbuf operations. - * Note: the total number of outgoing packets in the system (for - * all neighbors) is defined via QUEUEBUF_CONF_NUM */ -#ifdef TSCH_QUEUE_CONF_NUM_PER_NEIGHBOR -#define TSCH_QUEUE_NUM_PER_NEIGHBOR TSCH_QUEUE_CONF_NUM_PER_NEIGHBOR -#else -/* By default, round QUEUEBUF_CONF_NUM to next power of two - * (in the range [4;256]) */ -#if QUEUEBUF_CONF_NUM <= 4 -#define TSCH_QUEUE_NUM_PER_NEIGHBOR 4 -#elif QUEUEBUF_CONF_NUM <= 8 -#define TSCH_QUEUE_NUM_PER_NEIGHBOR 8 -#elif QUEUEBUF_CONF_NUM <= 16 -#define TSCH_QUEUE_NUM_PER_NEIGHBOR 16 -#elif QUEUEBUF_CONF_NUM <= 32 -#define TSCH_QUEUE_NUM_PER_NEIGHBOR 32 -#elif QUEUEBUF_CONF_NUM <= 64 -#define TSCH_QUEUE_NUM_PER_NEIGHBOR 64 -#elif QUEUEBUF_CONF_NUM <= 128 -#define TSCH_QUEUE_NUM_PER_NEIGHBOR 128 -#else -#define TSCH_QUEUE_NUM_PER_NEIGHBOR 256 -#endif -#endif - -/* The number of neighbor queues. There are two queues allocated at all times: - * one for EBs, one for broadcasts. Other queues are for unicast to neighbors */ -#ifdef TSCH_QUEUE_CONF_MAX_NEIGHBOR_QUEUES -#define TSCH_QUEUE_MAX_NEIGHBOR_QUEUES TSCH_QUEUE_CONF_MAX_NEIGHBOR_QUEUES -#else -#define TSCH_QUEUE_MAX_NEIGHBOR_QUEUES ((NBR_TABLE_CONF_MAX_NEIGHBORS) + 2) -#endif - -/* TSCH CSMA-CA parameters, see IEEE 802.15.4e-2012 */ -/* Min backoff exponent */ -#ifdef TSCH_CONF_MAC_MIN_BE -#define TSCH_MAC_MIN_BE TSCH_CONF_MAC_MIN_BE -#else -#define TSCH_MAC_MIN_BE 1 -#endif -/* Max backoff exponent */ -#ifdef TSCH_CONF_MAC_MAX_BE -#define TSCH_MAC_MAX_BE TSCH_CONF_MAC_MAX_BE -#else -#define TSCH_MAC_MAX_BE 5 -#endif -/* Max number of re-transmissions */ -#ifdef TSCH_CONF_MAC_MAX_FRAME_RETRIES -#define TSCH_MAC_MAX_FRAME_RETRIES TSCH_CONF_MAC_MAX_FRAME_RETRIES -#else -#define TSCH_MAC_MAX_FRAME_RETRIES 7 -#endif - -/*********** Callbacks *********/ - -#if BUILD_WITH_ORCHESTRA - -#ifndef TSCH_CALLBACK_NEW_TIME_SOURCE -#define TSCH_CALLBACK_NEW_TIME_SOURCE orchestra_callback_new_time_source -#endif /* TSCH_CALLBACK_NEW_TIME_SOURCE */ - -#ifndef TSCH_CALLBACK_PACKET_READY -#define TSCH_CALLBACK_PACKET_READY orchestra_callback_packet_ready -#endif /* TSCH_CALLBACK_PACKET_READY */ - -#endif /* BUILD_WITH_ORCHESTRA */ - -/* Called by TSCH when switching time source */ -#ifdef TSCH_CALLBACK_NEW_TIME_SOURCE -struct tsch_neighbor; -void TSCH_CALLBACK_NEW_TIME_SOURCE(const struct tsch_neighbor *old, const struct tsch_neighbor *new); -#endif - -/* Called by TSCH every time a packet is ready to be added to the send queue */ -#ifdef TSCH_CALLBACK_PACKET_READY -void TSCH_CALLBACK_PACKET_READY(void); -#endif - -/************ Types ***********/ - -/* TSCH packet information */ -struct tsch_packet { - struct queuebuf *qb; /* pointer to the queuebuf to be sent */ - mac_callback_t sent; /* callback for this packet */ - void *ptr; /* MAC callback parameter */ - uint8_t transmissions; /* #transmissions performed for this packet */ - uint8_t ret; /* status -- MAC return code */ - uint8_t header_len; /* length of header and header IEs (needed for link-layer security) */ - uint8_t tsch_sync_ie_offset; /* Offset within the frame used for quick update of EB ASN and join priority */ -}; - -/* TSCH neighbor information */ -struct tsch_neighbor { - /* Neighbors are stored as a list: "next" must be the first field */ - struct tsch_neighbor *next; - linkaddr_t addr; /* MAC address of the neighbor */ - uint8_t is_broadcast; /* is this neighbor a virtual neighbor used for broadcast (of data packets or EBs) */ - uint8_t is_time_source; /* is this neighbor a time source? */ - uint8_t backoff_exponent; /* CSMA backoff exponent */ - uint8_t backoff_window; /* CSMA backoff window (number of slots to skip) */ - uint8_t last_backoff_window; /* Last CSMA backoff window */ - uint8_t tx_links_count; /* How many links do we have to this neighbor? */ - uint8_t dedicated_tx_links_count; /* How many dedicated links do we have to this neighbor? */ - /* Array for the ringbuf. Contains pointers to packets. - * Its size must be a power of two to allow for atomic put */ - struct tsch_packet *tx_array[TSCH_QUEUE_NUM_PER_NEIGHBOR]; - /* Circular buffer of pointers to packet. */ - struct ringbufindex tx_ringbuf; -}; - /***** External Variables *****/ /* Broadcast and EB virtual neighbors */ @@ -167,49 +55,128 @@ extern struct tsch_neighbor *n_eb; /********** Functions *********/ -/* Add a TSCH neighbor */ +/** + * \brief Add a TSCH neighbor queue + * \param addr The link-layer address of the neighbor to be added + */ struct tsch_neighbor *tsch_queue_add_nbr(const linkaddr_t *addr); -/* Get a TSCH neighbor */ +/** + * \brief Get a TSCH neighbor + * \param addr The link-layer address of the neighbor we are looking for + * \return A pointer to the neighbor queue, NULL if not found + */ struct tsch_neighbor *tsch_queue_get_nbr(const linkaddr_t *addr); -/* Get a TSCH time source (we currently assume there is only one) */ +/** + * \brief Get the TSCH time source (we currently assume there is only one) + * \return The neighbor queue associated to the time source + */ struct tsch_neighbor *tsch_queue_get_time_source(void); -/* Update TSCH time source */ +/** + * \brief Update TSCH time source + * \param new_addr The address of the new TSCH time source + */ int tsch_queue_update_time_source(const linkaddr_t *new_addr); -/* Add packet to neighbor queue. Use same lockfree implementation as ringbuf.c (put is atomic) */ -struct tsch_packet *tsch_queue_add_packet(const linkaddr_t *addr, mac_callback_t sent, void *ptr); -/* Returns the number of packets currently in any TSCH queue */ +/** + * \brief Add packet to neighbor queue. Use same lockfree implementation as ringbuf.c (put is atomic) + * \param addr The address of the targetted neighbor, &tsch_broadcast_address for broadcast + * \param max_transmissions The number of MAC retries + * \param sent The MAC packet sent callback + * \param ptr The MAC packet send callback parameter + * \return The newly created packet if any, NULL otherwise + */ +struct tsch_packet *tsch_queue_add_packet(const linkaddr_t *addr, uint8_t max_transmissions, + mac_callback_t sent, void *ptr); +/** + * \brief Returns the number of packets currently in all TSCH queues + * \return The number of packets currently in all TSCH queues + */ int tsch_queue_global_packet_count(void); -/* Returns the number of packets currently a given neighbor queue */ +/** + * \brief Returns the number of packets currently a given neighbor queue + * \param addr The link-layer address of the neighbor we are interested in + * \return The number of packets in the neighbor's queue + */ int tsch_queue_packet_count(const linkaddr_t *addr); -/* Remove first packet from a neighbor queue. The packet is stored in a separate - * dequeued packet list, for later processing. Return the packet. */ +/** + * \brief Remove first packet from a neighbor queue. The packet is stored in a separate + * dequeued packet list, for later processing. + * \param n The neighbor queue + * \return The packet that was removed if any, NULL otherwise + */ struct tsch_packet *tsch_queue_remove_packet_from_queue(struct tsch_neighbor *n); -/* Free a packet */ +/** + * \brief Free a packet + * \param p The packet to be freed + */ void tsch_queue_free_packet(struct tsch_packet *p); -/* Updates neighbor queue state after a transmission */ +/** + * \brief Updates neighbor queue state after a transmission + * \param n The neighbor queue we just sent from + * \param p The packet that was just sent + * \param link The TSCH link used for Tx + * \param mac_tx_status The MAC status (see mac.h) + * \return 1 if the packet remains in queue after the call, 0 if it was removed + */ int tsch_queue_packet_sent(struct tsch_neighbor *n, struct tsch_packet *p, struct tsch_link *link, uint8_t mac_tx_status); -/* Reset neighbor queues */ +/** + * \brief Reset neighbor queues module + */ void tsch_queue_reset(void); -/* Deallocate neighbors with empty queue */ +/** + * \brief Deallocate all neighbors with empty queue + */ void tsch_queue_free_unused_neighbors(void); -/* Is the neighbor queue empty? */ +/** + * \brief Is the neighbor queue empty? + * \param n The neighbor queue + * \return 1 if empty, 0 otherwise + */ int tsch_queue_is_empty(const struct tsch_neighbor *n); -/* Returns the first packet from a neighbor queue */ +/** + * \brief Returns the first packet that can be sent from a queue on a given link + * \param n The neighbor queue + * \param link The link + * \return The next packet to be sent for the neighbor on the given link, if any, else NULL + */ struct tsch_packet *tsch_queue_get_packet_for_nbr(const struct tsch_neighbor *n, struct tsch_link *link); -/* Returns the head packet from a neighbor queue (from neighbor address) */ +/** + * \brief Returns the first packet that can be sent to a given address on a given link + * \param addr The target link-layer address + * \param link The link + * \return The next packet to be sent for to the given address on the given link, if any, else NULL + */ struct tsch_packet *tsch_queue_get_packet_for_dest_addr(const linkaddr_t *addr, struct tsch_link *link); -/* Returns the head packet of any neighbor queue with zero backoff counter. - * Writes pointer to the neighbor in *n */ +/** + * \brief Gets the head packet of any neighbor queue with zero backoff counter. + * \param n A pointer where to store the neighbor queue to be used for Tx + * \param link The link to be used for Tx + * \return The packet if any, else NULL + */ struct tsch_packet *tsch_queue_get_unicast_packet_for_any(struct tsch_neighbor **n, struct tsch_link *link); -/* May the neighbor transmit over a share link? */ +/** + * \brief Is the neighbor backoff timer expired? + * \param n The neighbor queue + * \return 1 if the backoff has expired (neighbor ready to transmit on a shared link), 0 otherwise + */ int tsch_queue_backoff_expired(const struct tsch_neighbor *n); -/* Reset neighbor backoff */ +/** + * \brief Reset neighbor backoff + * \param n The neighbor queue + */ void tsch_queue_backoff_reset(struct tsch_neighbor *n); -/* Increment backoff exponent, pick a new window */ +/** + * \brief Increment backoff exponent of a given neighbor queue, pick a new window + * \param n The neighbor queue + */ void tsch_queue_backoff_inc(struct tsch_neighbor *n); -/* Decrement backoff window for all queues directed at dest_addr */ +/** + * \brief Decrement backoff window for the queue(s) able to Tx to a given address + * \param dest_addr The target address, &tsch_broadcast_address for broadcast + */ void tsch_queue_update_all_backoff_windows(const linkaddr_t *dest_addr); -/* Initialize TSCH queue module */ +/** + * \brief Initialize TSCH queue module + */ void tsch_queue_init(void); #endif /* __TSCH_QUEUE_H__ */ diff --git a/os/net/mac/tsch/tsch-rpl.c b/os/net/mac/tsch/tsch-rpl.c index ec3f24d8b4f3fb4247d8441d9df5530cf9b47cc5..951648d91d5f45d34f309377a95a6019b85f6427 100644 --- a/os/net/mac/tsch/tsch-rpl.c +++ b/os/net/mac/tsch/tsch-rpl.c @@ -40,21 +40,20 @@ * @{ */ +#include "contiki.h" + #if UIP_CONF_IPV6_RPL -#include "contiki.h" -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ +#include "net/routing/routing.h" #include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-private.h" -#include "net/mac/tsch/tsch-schedule.h" -#include "net/mac/tsch/tsch-log.h" -#include "net/mac/tsch/tsch-rpl.h" -#include "tsch-rpl.h" +#include "net/link-stats.h" + +#if ROUTING_CONF_RPL_LITE +#include "net/routing/rpl-lite/rpl.h" +#elif ROUTING_CONF_RPL_CLASSIC +#include "net/routing/rpl-classic/rpl.h" +#include "net/routing/rpl-classic/rpl-private.h" +#endif /* Log configuration */ #include "sys/log.h" @@ -66,7 +65,7 @@ void tsch_rpl_callback_ka_sent(int status, int transmissions) { - rpl_link_callback(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), status, transmissions); + NETSTACK_ROUTING.link_callback(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), status, transmissions); } /*---------------------------------------------------------------------------*/ /* To use, set #define TSCH_CALLBACK_JOINING_NETWORK tsch_rpl_callback_joining_network */ @@ -81,14 +80,12 @@ tsch_rpl_callback_joining_network(void) void tsch_rpl_callback_leaving_network(void) { - rpl_dag_t *dag = rpl_get_any_dag(); - if(dag != NULL) { -#if UIP_CONF_IPV6_RPL_LITE - rpl_local_repair("TSCH leaving"); -#else - rpl_local_repair(dag->instance); -#endif - } + /* Forget past link statistics. If we are leaving a TSCH + network, there are changes we've been out of sync in the recent past, and + as a result have irrelevant link statistices. */ + link_stats_reset(); + /* RPL local repair */ + NETSTACK_ROUTING.local_repair("TSCH leaving"); } /*---------------------------------------------------------------------------*/ /* Set TSCH EB period based on current RPL DIO period. @@ -100,7 +97,7 @@ tsch_rpl_callback_new_dio_interval(clock_time_t dio_interval) rpl_dag_t *dag; rpl_rank_t root_rank; rpl_rank_t dag_rank; -#if UIP_CONF_IPV6_RPL_LITE +#if ROUTING_CONF_RPL_LITE dag = &curr_instance.dag; root_rank = ROOT_RANK; dag_rank = DAG_RANK(dag->rank); diff --git a/os/net/mac/tsch/tsch-rpl.h b/os/net/mac/tsch/tsch-rpl.h index 15be760f5e2eda642f3a00b7229c2d74f32745b9..23a148db86833e051f12f4830c2b77c8ed60db2a 100644 --- a/os/net/mac/tsch/tsch-rpl.h +++ b/os/net/mac/tsch/tsch-rpl.h @@ -31,6 +31,8 @@ /** * \addtogroup tsch * @{ + * \file + * TSCH-RPL interaction */ #ifndef __TSCH_RPL_H__ @@ -38,29 +40,44 @@ /********** Includes **********/ -#if UIP_CONF_IPV6_RPL_LITE == 1 -#include "net/rpl-lite/rpl.h" -#else /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/rpl-classic/rpl.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */ -#include "net/mac/tsch/tsch-queue.h" +#include "net/routing/routing.h" +#if ROUTING_CONF_RPL_LITE +#include "net/routing/rpl-lite/rpl.h" +#elif ROUTING_CONF_RPL_CLASSIC +#include "net/routing/rpl-classic/rpl.h" +#endif /********** Functions *********/ -/* Keep-alives packet sent callback. - * To use, set #define TSCH_CALLBACK_KA_SENT tsch_rpl_callback_ka_sent */ +/** +* \brief Report statiscs from KA packet sent in RPL. +* To use, set TSCH_CALLBACK_KA_SENT to tsch_rpl_callback_ka_sent +* \param status The packet sent status +* \param transmissions The total number of transmissions +*/ void tsch_rpl_callback_ka_sent(int status, int transmissions); -/* To use, set #define TSCH_CALLBACK_JOINING_NETWORK tsch_rpl_callback_joining_network */ +/** + * \brief Let RPL know that TSCH joined a new network. + * To use, set TSCH_CALLBACK_JOINING_NETWORK to tsch_rpl_callback_joining_network + */ void tsch_rpl_callback_joining_network(void); -/* Upon leaving a TSCH network, perform a local repair - * (cleanup neighbor state, reset Trickle timer etc) - * To use, set #define TSCH_CALLBACK_LEAVING_NETWORK tsch_rpl_callback_leaving_network */ +/** + * \brief Let RPL know that TSCH joined a new network. Triggers a local repair. + * To use, set TSCH_CALLBACK_LEAVING_NETWORK to tsch_rpl_callback_leaving_network + */ void tsch_rpl_callback_leaving_network(void); -/* Set TSCH EB period based on current RPL DIO period. - * To use, set #define RPL_CALLBACK_NEW_DIO_INTERVAL tsch_rpl_callback_new_dio_interval */ +/** + * \brief Set TSCH EB period based on current RPL DIO period. + * To use, set RPL_CALLBACK_NEW_DIO_INTERVAL to tsch_rpl_callback_new_dio_interval + * \param dio_interval The new DIO interval in clock ticks + */ void tsch_rpl_callback_new_dio_interval(clock_time_t dio_interval); -/* Set TSCH time source based on current RPL preferred parent. - * To use, set #define RPL_CALLBACK_PARENT_SWITCH tsch_rpl_callback_parent_switch */ +/** + * \brief Set TSCH time source based on current RPL preferred parent. + * To use, set RPL_CALLBACK_PARENT_SWITCH to tsch_rpl_callback_parent_switch + * \param old The old RPL parent + * \param new The new RPL parent + */ void tsch_rpl_callback_parent_switch(rpl_parent_t *old, rpl_parent_t *new); #endif /* __TSCH_RPL_H__ */ diff --git a/os/net/mac/tsch/tsch-schedule.c b/os/net/mac/tsch/tsch-schedule.c index dd31afecd1574099f26f25ff1b11de1bc494b1f3..70a6b92ae224797a1c1b0f2247ed3ff3568689dd 100644 --- a/os/net/mac/tsch/tsch-schedule.c +++ b/os/net/mac/tsch/tsch-schedule.c @@ -50,11 +50,6 @@ #include "net/packetbuf.h" #include "net/queuebuf.h" #include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-queue.h" -#include "net/mac/tsch/tsch-private.h" -#include "net/mac/tsch/tsch-packet.h" -#include "net/mac/tsch/tsch-schedule.h" -#include "net/mac/tsch/tsch-log.h" #include "net/mac/framer/frame802154.h" #include "sys/process.h" #include "sys/rtimer.h" @@ -452,16 +447,15 @@ tsch_schedule_print(void) if(!tsch_is_locked()) { struct tsch_slotframe *sf = list_head(slotframe_list); - printf("Schedule: slotframe list\n"); + LOG_PRINT("----- start slotframe list -----\n"); while(sf != NULL) { struct tsch_link *l = list_head(sf->links_list); - printf("[Slotframe] Handle %u, size %u\n", sf->handle, sf->size.val); - printf("List of links:\n"); + LOG_PRINT("Slotframe Handle %u, size %u\n", sf->handle, sf->size.val); while(l != NULL) { - printf("[Link] Options %02x, type %u, timeslot %u, channel offset %u, address %u\n", + LOG_PRINT("* Link Options %02x, type %u, timeslot %u, channel offset %u, address %u\n", l->link_options, l->link_type, l->timeslot, l->channel_offset, l->addr.u8[7]); l = list_item_next(l); } @@ -469,7 +463,7 @@ tsch_schedule_print(void) sf = list_item_next(sf); } - printf("Schedule: end of slotframe list\n"); + LOG_PRINT("----- end slotframe list -----\n"); } } /*---------------------------------------------------------------------------*/ diff --git a/os/net/mac/tsch/tsch-schedule.h b/os/net/mac/tsch/tsch-schedule.h index 12699b0e3bfb29b0e78d2bd4a23bb7514bd6c283..d98a744f379e564df54b04630d8bd836a0b2398c 100644 --- a/os/net/mac/tsch/tsch-schedule.h +++ b/os/net/mac/tsch/tsch-schedule.h @@ -33,6 +33,8 @@ /** * \addtogroup tsch * @{ + * \file + * TSCH scheduling engine */ #ifndef __TSCH_SCHEDULE_H__ @@ -41,132 +43,119 @@ /********** Includes **********/ #include "contiki.h" -#include "lib/list.h" -#include "net/mac/tsch/tsch-private.h" -#include "net/mac/tsch/tsch-queue.h" -#include "net/mac/tsch/tsch-slot-operation.h" #include "net/linkaddr.h" -/******** Configuration *******/ - -/* Initializes TSCH with a 6TiSCH minimal schedule */ -#ifdef TSCH_SCHEDULE_CONF_WITH_6TISCH_MINIMAL -#define TSCH_SCHEDULE_WITH_6TISCH_MINIMAL TSCH_SCHEDULE_CONF_WITH_6TISCH_MINIMAL -#else -#define TSCH_SCHEDULE_WITH_6TISCH_MINIMAL (!(BUILD_WITH_ORCHESTRA)) -#endif - -/* 6TiSCH Minimal schedule slotframe length */ -#ifdef TSCH_SCHEDULE_CONF_DEFAULT_LENGTH -#define TSCH_SCHEDULE_DEFAULT_LENGTH TSCH_SCHEDULE_CONF_DEFAULT_LENGTH -#else -#define TSCH_SCHEDULE_DEFAULT_LENGTH 7 -#endif - -/* Max number of TSCH slotframes */ -#ifdef TSCH_SCHEDULE_CONF_MAX_SLOTFRAMES -#define TSCH_SCHEDULE_MAX_SLOTFRAMES TSCH_SCHEDULE_CONF_MAX_SLOTFRAMES -#else -#define TSCH_SCHEDULE_MAX_SLOTFRAMES 4 -#endif - -/* Max number of links */ -#ifdef TSCH_SCHEDULE_CONF_MAX_LINKS -#define TSCH_SCHEDULE_MAX_LINKS TSCH_SCHEDULE_CONF_MAX_LINKS -#else -#define TSCH_SCHEDULE_MAX_LINKS 32 -#endif - -/********** Constants *********/ - -/* Link options */ -#define LINK_OPTION_TX 1 -#define LINK_OPTION_RX 2 -#define LINK_OPTION_SHARED 4 -#define LINK_OPTION_TIME_KEEPING 8 - -/************ Types ***********/ - -/* 802.15.4e link types. - * LINK_TYPE_ADVERTISING_ONLY is an extra one: for EB-only links. */ -enum link_type { LINK_TYPE_NORMAL, LINK_TYPE_ADVERTISING, LINK_TYPE_ADVERTISING_ONLY }; - -struct tsch_link { - /* Links are stored as a list: "next" must be the first field */ - struct tsch_link *next; - /* Unique identifier */ - uint16_t handle; - /* MAC address of neighbor */ - linkaddr_t addr; - /* Slotframe identifier */ - uint16_t slotframe_handle; - /* Identifier of Slotframe to which this link belongs - * Unused. */ - /* uint8_t handle; */ - /* Timeslot for this link */ - uint16_t timeslot; - /* Channel offset for this link */ - uint16_t channel_offset; - /* A bit string that defines - * b0 = Transmit, b1 = Receive, b2 = Shared, b3 = Timekeeping, b4 = reserved */ - uint8_t link_options; - /* Type of link. NORMAL = 0. ADVERTISING = 1, and indicates - the link may be used to send an Enhanced beacon. */ - enum link_type link_type; - /* Any other data for upper layers */ - void *data; -}; - -struct tsch_slotframe { - /* Slotframes are stored as a list: "next" must be the first field */ - struct tsch_slotframe *next; - /* Unique identifier */ - uint16_t handle; - /* Number of timeslots in the slotframe. - * Stored as struct asn_divisor_t because we often need ASN%size */ - struct tsch_asn_divisor_t size; - /* List of links belonging to this slotframe */ - LIST_STRUCT(links_list); -}; - /********** Functions *********/ -/* Module initialization, call only once at startup. Returns 1 is success, 0 if failure. */ +/** + * \brief Module initialization, call only once at init + * \return 1 if success, 0 if failure + */ int tsch_schedule_init(void); -/* Create a 6TiSCH minimal schedule */ +/** + * \brief Create a 6tisch minimal schedule with length TSCH_SCHEDULE_DEFAULT_LENGTH + */ void tsch_schedule_create_minimal(void); -/* Prints out the current schedule (all slotframes and links) */ +/** + * \brief Prints out the current schedule (all slotframes and links) + */ void tsch_schedule_print(void); -/* Adds and returns a slotframe (NULL if failure) */ + +/** + * \brief Creates and adds a new slotframe + * \param handle the slotframe handle + * \param size the slotframe size + * \return the new slotframe, NULL if failure + */ struct tsch_slotframe *tsch_schedule_add_slotframe(uint16_t handle, uint16_t size); -/* Looks for a slotframe from a handle */ + +/** + * \brief Looks up a slotframe by handle + * \param handle the slotframe handle + * \return the slotframe with required handle, if any. NULL otherwise. + */ struct tsch_slotframe *tsch_schedule_get_slotframe_by_handle(uint16_t handle); -/* Removes a slotframe Return 1 if success, 0 if failure */ + +/** + * \brief Removes a slotframe + * \param slotframe The slotframe to be removed + * \return 1 if success, 0 if failure + */ int tsch_schedule_remove_slotframe(struct tsch_slotframe *slotframe); -/* Removes all slotframes, resulting in an empty schedule */ + +/** + * \brief Removes all slotframes, resulting in an empty schedule + * \return 1 if success, 0 if failure + */ int tsch_schedule_remove_all_slotframes(void); -/* Returns next slotframe */ -struct tsch_slotframe *tsch_schedule_slotframes_next(struct tsch_slotframe *sf); -/* Adds a link to a slotframe, return a pointer to it (NULL if failure) */ +/** + * \brief Adds a link to a slotframe + * \param slotframe The slotframe that will contain the new link + * \param link_options The link options, as a bitfield (LINK_OPTION_* flags) + * \param link_type The link type (advertising, normal) + * \param address The link address of the intended destination. Use &tsch_broadcast_address for a slot towards any neighbor + * \param timeslot The link timeslot within the slotframe + * \param channel_offset The link channel offset + * \return A pointer to the new link, NULL if failure + */ struct tsch_link *tsch_schedule_add_link(struct tsch_slotframe *slotframe, uint8_t link_options, enum link_type link_type, const linkaddr_t *address, uint16_t timeslot, uint16_t channel_offset); -/* Looks for a link from a handle */ +/** +* \brief Looks for a link from a handle +* \param handle The target handle +* \return The link with required handle, if any. Otherwise, NULL +*/ struct tsch_link *tsch_schedule_get_link_by_handle(uint16_t handle); -/* Looks within a slotframe for a link with a given timeslot */ + +/** + * \brief Looks within a slotframe for a link with a given timeslot + * \param slotframe The desired slotframe + * \param timeslot The desired timeslot + * \return The link if found, NULL otherwise + */ struct tsch_link *tsch_schedule_get_link_by_timeslot(struct tsch_slotframe *slotframe, uint16_t timeslot); -/* Removes a link. Return 1 if success, 0 if failure */ + +/** + * \brief Removes a link + * \param slotframe The slotframe the link belongs to + * \param l The link to be removed + * \return 1 if success, 0 if failure + */ int tsch_schedule_remove_link(struct tsch_slotframe *slotframe, struct tsch_link *l); -/* Removes a link from slotframe and timeslot. Return a 1 if success, 0 if failure */ + +/** + * \brief Removes a link from a slotframe and timeslot + * \param slotframe The slotframe where to look for the link + * \param timeslot The timeslot where to look for the link within the target slotframe + * \return 1 if success, 0 if failure + */ int tsch_schedule_remove_link_by_timeslot(struct tsch_slotframe *slotframe, uint16_t timeslot); -/* Returns the next active link after a given ASN, and a backup link (for the same ASN, with Rx flag) */ + +/** + * \brief Returns the next active link after a given ASN, and a backup link (for the same ASN, with Rx flag) + * \param asn The base ASN, from which we look for the next active link + * \param time_offset A pointer to uint16_t where to store the time offset between base ASN and link found + * \param backup_link A pointer where to write the address of a backup link, to be executed should the original be no longer active at wakeup + * \return The next active link if any, NULL otherwise + */ struct tsch_link * tsch_schedule_get_next_active_link(struct tsch_asn_t *asn, uint16_t *time_offset, struct tsch_link **backup_link); -/* Access to slotframe list */ + +/** + * \brief Access the first item in the list of slotframes + * \return The first slotframe in the schedule if any, NULL otherwise + */ struct tsch_slotframe *tsch_schedule_slotframe_head(void); + +/** + * \brief Access the next item in the list of slotframes + * \param sf The current slotframe (item in the list) + * \return The next slotframe if any, NULL otherwise + */ struct tsch_slotframe *tsch_schedule_slotframe_next(struct tsch_slotframe *sf); #endif /* __TSCH_SCHEDULE_H__ */ diff --git a/os/net/mac/tsch/tsch-security.c b/os/net/mac/tsch/tsch-security.c index d53dd930707c9cb9a44c5e9433d38124eccfec57..1c4266626f46f7f5ede1ebc14e7d529c6a48d759 100644 --- a/os/net/mac/tsch/tsch-security.c +++ b/os/net/mac/tsch/tsch-security.c @@ -44,11 +44,6 @@ #include "contiki.h" #include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-packet.h" -#include "net/mac/tsch/tsch-private.h" -#include "net/mac/tsch/tsch-schedule.h" -#include "net/mac/tsch/tsch-security.h" -#include "net/mac/tsch/tsch-log.h" #include "net/mac/framer/frame802154.h" #include "net/mac/framer/framer-802154.h" #include "net/netstack.h" diff --git a/os/net/mac/tsch/tsch-security.h b/os/net/mac/tsch/tsch-security.h index 4ca4be07e877abf7dcda90776e9ad7eeddb98f7e..56c854414ff8518bb8bb28ac8fa816536efbf60c 100644 --- a/os/net/mac/tsch/tsch-security.h +++ b/os/net/mac/tsch/tsch-security.h @@ -33,6 +33,8 @@ /** * \addtogroup tsch * @{ + * \file + * TSCH security */ #ifndef __TSCH_SECURITY_H__ @@ -41,18 +43,16 @@ /********** Includes **********/ #include "contiki.h" -#include "net/mac/tsch/tsch-asn.h" -#include "net/mac/tsch/tsch-private.h" #include "net/mac/framer/frame802154.h" #include "net/mac/framer/frame802154e-ie.h" #include "net/mac/llsec802154.h" -/******** Configuration *******/ +/********** Configurarion *********/ /* To enable TSCH security: - * - set LLSEC802154_CONF_ENABLED - * - set LLSEC802154_CONF_USES_EXPLICIT_KEYS - * */ +* - set LLSEC802154_CONF_ENABLED +* - set LLSEC802154_CONF_USES_EXPLICIT_KEYS +* */ #if LLSEC802154_ENABLED && !LLSEC802154_USES_EXPLICIT_KEYS #error LLSEC802154_ENABLED set but LLSEC802154_USES_EXPLICIT_KEYS unset @@ -114,8 +114,9 @@ #define TSCH_SECURITY_KEY_SEC_LEVEL_OTHER 5 /* Encryption + MIC-32, as per 6TiSCH minimal */ #endif -/************ Types ***********/ +/********** Data types *********/ +/* AES-128 key */ typedef uint8_t aes_key[16]; /********** Functions *********/ diff --git a/os/net/mac/tsch/tsch-slot-operation.c b/os/net/mac/tsch/tsch-slot-operation.c index 3596b913c8b2c19d898ed8b7a46f3169977e1043..c4bb25e88ea877c3e839c60753733bc7cbf5fde3 100644 --- a/os/net/mac/tsch/tsch-slot-operation.c +++ b/os/net/mac/tsch/tsch-slot-operation.c @@ -52,17 +52,10 @@ #include "net/queuebuf.h" #include "net/mac/framer/framer-802154.h" #include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-slot-operation.h" -#include "net/mac/tsch/tsch-queue.h" -#include "net/mac/tsch/tsch-private.h" -#include "net/mac/tsch/tsch-log.h" -#include "net/mac/tsch/tsch-packet.h" -#include "net/mac/tsch/tsch-security.h" -#include "net/mac/tsch/tsch-adaptive-timesync.h" -#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 +#if CONTIKI_TARGET_COOJA #include "lib/simEnvChange.h" #include "sys/cooja_mt.h" -#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */ +#endif /* CONTIKI_TARGET_COOJA */ #include "sys/log.h" /* TSCH debug macros, i.e. to set LEDs or GPIOs on various TSCH @@ -107,7 +100,7 @@ #if RTIMER_SECOND < (32 * 1024) #error "TSCH: RTIMER_SECOND < (32 * 1024)" #endif -#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 +#if CONTIKI_TARGET_COOJA /* Use 0 usec guard time for Cooja Mote with a 1 MHz Rtimer*/ #define RTIMER_GUARD 0u #elif RTIMER_SECOND >= 200000 @@ -208,10 +201,10 @@ tsch_get_lock(void) busy_wait = 1; busy_wait_time = RTIMER_NOW(); while(tsch_in_slot_operation) { -#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 +#if CONTIKI_TARGET_COOJA simProcessRunValue = 1; cooja_mt_yield(); -#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */ +#endif /* CONTIKI_TARGET_COOJA */ } busy_wait_time = RTIMER_NOW() - busy_wait_time; } @@ -297,15 +290,16 @@ tsch_schedule_slot_operation(struct rtimer *tm, rtimer_clock_t ref_time, rtimer_ "!dl-miss %s %d %d", str, (int)(now-ref_time), (int)offset); ); - - return 0; - } - ref_time += offset; - r = rtimer_set(tm, ref_time, 1, (void (*)(struct rtimer *, void *))tsch_slot_operation, NULL); - if(r != RTIMER_OK) { - return 0; + } else { + r = rtimer_set(tm, ref_time + offset, 1, (void (*)(struct rtimer *, void *))tsch_slot_operation, NULL); + if(r == RTIMER_OK) { + return 1; + } } - return 1; + + /* block until the time to schedule comes */ + BUSYWAIT_UNTIL_ABS(0, ref_time, offset); + return 0; } /*---------------------------------------------------------------------------*/ /* Schedule slot operation conditionally, and YIELD if success only. @@ -315,8 +309,8 @@ tsch_schedule_slot_operation(struct rtimer *tm, rtimer_clock_t ref_time, rtimer_ do { \ if(tsch_schedule_slot_operation(tm, ref_time, offset - RTIMER_GUARD, str)) { \ PT_YIELD(pt); \ + BUSYWAIT_UNTIL_ABS(0, ref_time, offset); \ } \ - BUSYWAIT_UNTIL_ABS(0, ref_time, offset); \ } while(0); /*---------------------------------------------------------------------------*/ /* Get EB, broadcast or unicast packet to be sent, and target neighbor. */ @@ -1010,12 +1004,12 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr)) TSCH_ASN_INC(tsch_current_asn, timeslot_diff); /* Time to next wake up */ time_to_next_active_slot = timeslot_diff * tsch_timing[tsch_ts_timeslot_length] + drift_correction; + time_to_next_active_slot += tsch_timesync_adaptive_compensate(time_to_next_active_slot); drift_correction = 0; is_drift_correction_used = 0; /* Update current slot start */ prev_slot_start = current_slot_start; current_slot_start += time_to_next_active_slot; - current_slot_start += tsch_timesync_adaptive_compensate(time_to_next_active_slot); } while(!tsch_schedule_slot_operation(t, prev_slot_start, time_to_next_active_slot, "main")); } diff --git a/os/net/mac/tsch/tsch-slot-operation.h b/os/net/mac/tsch/tsch-slot-operation.h index 0c0ae60b64d31ca50ce22c249f11be397329dfe7..1c71c55870fee17541813673bd7fd5a8d89c5e48 100644 --- a/os/net/mac/tsch/tsch-slot-operation.h +++ b/os/net/mac/tsch/tsch-slot-operation.h @@ -33,6 +33,8 @@ /** * \addtogroup tsch * @{ + * \file + * TSCH runtime operation within timeslots */ #ifndef __TSCH_SLOT_OPERATION_H__ @@ -42,61 +44,6 @@ #include "contiki.h" #include "lib/ringbufindex.h" -#include "net/mac/tsch/tsch-packet.h" -#include "net/mac/tsch/tsch-private.h" - -/******** Configuration *******/ - -/* Size of the ring buffer storing dequeued outgoing packets (only an array of pointers). - * Must be power of two, and greater or equal to QUEUEBUF_NUM */ -#ifdef TSCH_CONF_DEQUEUED_ARRAY_SIZE -#define TSCH_DEQUEUED_ARRAY_SIZE TSCH_CONF_DEQUEUED_ARRAY_SIZE -#else -/* By default, round QUEUEBUF_CONF_NUM to next power of two - * (in the range [4;256]) */ -#if QUEUEBUF_CONF_NUM <= 4 -#define TSCH_DEQUEUED_ARRAY_SIZE 4 -#elif QUEUEBUF_CONF_NUM <= 8 -#define TSCH_DEQUEUED_ARRAY_SIZE 8 -#elif QUEUEBUF_CONF_NUM <= 16 -#define TSCH_DEQUEUED_ARRAY_SIZE 16 -#elif QUEUEBUF_CONF_NUM <= 32 -#define TSCH_DEQUEUED_ARRAY_SIZE 32 -#elif QUEUEBUF_CONF_NUM <= 64 -#define TSCH_DEQUEUED_ARRAY_SIZE 64 -#elif QUEUEBUF_CONF_NUM <= 128 -#define TSCH_DEQUEUED_ARRAY_SIZE 128 -#else -#define TSCH_DEQUEUED_ARRAY_SIZE 256 -#endif -#endif - -/* Size of the ring buffer storing incoming packets. - * Must be power of two */ -#ifdef TSCH_CONF_MAX_INCOMING_PACKETS -#define TSCH_MAX_INCOMING_PACKETS TSCH_CONF_MAX_INCOMING_PACKETS -#else -#define TSCH_MAX_INCOMING_PACKETS 4 -#endif - -/*********** Callbacks *********/ - -/* Called by TSCH form interrupt after receiving a frame, enabled upper-layer to decide - * whether to ACK or NACK */ -#ifdef TSCH_CALLBACK_DO_NACK -int TSCH_CALLBACK_DO_NACK(struct tsch_link *link, linkaddr_t *src, linkaddr_t *dst); -#endif - -/************ Types ***********/ - -/* Stores data about an incoming packet */ -struct input_packet { - uint8_t payload[TSCH_PACKET_MAX_LEN]; /* Packet payload */ - struct tsch_asn_t rx_asn; /* ASN when the packet was received */ - int len; /* Packet len */ - int16_t rssi; /* RSSI for this packet */ - uint8_t channel; /* Channel we received the packet on */ -}; /***** External Variables *****/ @@ -113,19 +60,45 @@ extern clock_time_t last_sync_time; /********** Functions *********/ -/* Returns a 802.15.4 channel from an ASN and channel offset */ +/** + * Returns a 802.15.4 channel from an ASN and channel offset. Basically adds + * The offset to the ASN and performs a hopping sequence lookup. + * + * \param asn A given ASN + * \param channel_offset A given channel offset + * \return The resulting channel + */ uint8_t tsch_calculate_channel(struct tsch_asn_t *asn, uint8_t channel_offset); -/* Is TSCH locked? */ +/** + * Checks if the TSCH lock is set. Accesses to global structures outside of + * interrupts must be done through the lock, unless the sturcutre has + * atomic read/write + * + * \return 1 if the lock is taken, 0 otherwise + */ int tsch_is_locked(void); -/* Lock TSCH (no link operation) */ +/** + * Takes the TSCH lock. When the lock is taken, slot operation will be skipped + * until release. + * + * \return 1 if the lock was successfully taken, 0 otherwise + */ int tsch_get_lock(void); -/* Release TSCH lock */ +/** + * Releases the TSCH lock. + */ void tsch_release_lock(void); -/* Set global time before starting slot operation, - * with a rtimer time and an ASN */ +/** + * Set global time before starting slot operation, with a rtimer time and an ASN + * + * \param next_slot_start the time to the start of the next slot, in rtimer ticks + * \param next_slot_asn the ASN of the next slot + */ void tsch_slot_operation_sync(rtimer_clock_t next_slot_start, struct tsch_asn_t *next_slot_asn); -/* Start actual slot operation */ +/** + * Start actual slot operation + */ void tsch_slot_operation_start(void); #endif /* __TSCH_SLOT_OPERATION_H__ */ diff --git a/os/net/mac/tsch/tsch-types.h b/os/net/mac/tsch/tsch-types.h new file mode 100644 index 0000000000000000000000000000000000000000..20f9911f6812f7846a4806b89d6a01dc53d99cbb --- /dev/null +++ b/os/net/mac/tsch/tsch-types.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2015, SICS Swedish ICT. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** +* \addtogroup tsch +* @{ + * \file + * TSCH types + * \author + * Simon Duquennoy <simonduq@sics.se> + */ + +#ifndef __TSCH_TYPES_H__ +#define __TSCH_TYPES_H__ + +/********** Includes **********/ + +#include "net/mac/tsch/tsch-asn.h" +#include "lib/list.h" +#include "lib/ringbufindex.h" + +/********** Data types **********/ + +/** \brief 802.15.4e link types. LINK_TYPE_ADVERTISING_ONLY is an extra one: for EB-only links. */ +enum link_type { LINK_TYPE_NORMAL, LINK_TYPE_ADVERTISING, LINK_TYPE_ADVERTISING_ONLY }; + +/** \brief An IEEE 802.15.4-2015 TSCH link (also called cell or slot) */ +struct tsch_link { + /* Links are stored as a list: "next" must be the first field */ + struct tsch_link *next; + /* Unique identifier */ + uint16_t handle; + /* MAC address of neighbor */ + linkaddr_t addr; + /* Slotframe identifier */ + uint16_t slotframe_handle; + /* Identifier of Slotframe to which this link belongs + * Unused. */ + /* uint8_t handle; */ + /* Timeslot for this link */ + uint16_t timeslot; + /* Channel offset for this link */ + uint16_t channel_offset; + /* A bit string that defines + * b0 = Transmit, b1 = Receive, b2 = Shared, b3 = Timekeeping, b4 = reserved */ + uint8_t link_options; + /* Type of link. NORMAL = 0. ADVERTISING = 1, and indicates + the link may be used to send an Enhanced beacon. */ + enum link_type link_type; + /* Any other data for upper layers */ + void *data; +}; + +/** \brief 802.15.4e slotframe (contains links) */ +struct tsch_slotframe { + /* Slotframes are stored as a list: "next" must be the first field */ + struct tsch_slotframe *next; + /* Unique identifier */ + uint16_t handle; + /* Number of timeslots in the slotframe. + * Stored as struct asn_divisor_t because we often need ASN%size */ + struct tsch_asn_divisor_t size; + /* List of links belonging to this slotframe */ + LIST_STRUCT(links_list); +}; + +/** \brief TSCH packet information */ +struct tsch_packet { + struct queuebuf *qb; /* pointer to the queuebuf to be sent */ + mac_callback_t sent; /* callback for this packet */ + void *ptr; /* MAC callback parameter */ + uint8_t transmissions; /* #transmissions performed for this packet */ + uint8_t max_transmissions; /* maximal number of Tx before dropping the packet */ + uint8_t ret; /* status -- MAC return code */ + uint8_t header_len; /* length of header and header IEs (needed for link-layer security) */ + uint8_t tsch_sync_ie_offset; /* Offset within the frame used for quick update of EB ASN and join priority */ +}; + +/** \brief TSCH neighbor information */ +struct tsch_neighbor { + /* Neighbors are stored as a list: "next" must be the first field */ + struct tsch_neighbor *next; + linkaddr_t addr; /* MAC address of the neighbor */ + uint8_t is_broadcast; /* is this neighbor a virtual neighbor used for broadcast (of data packets or EBs) */ + uint8_t is_time_source; /* is this neighbor a time source? */ + uint8_t backoff_exponent; /* CSMA backoff exponent */ + uint8_t backoff_window; /* CSMA backoff window (number of slots to skip) */ + uint8_t last_backoff_window; /* Last CSMA backoff window */ + uint8_t tx_links_count; /* How many links do we have to this neighbor? */ + uint8_t dedicated_tx_links_count; /* How many dedicated links do we have to this neighbor? */ + /* Array for the ringbuf. Contains pointers to packets. + * Its size must be a power of two to allow for atomic put */ + struct tsch_packet *tx_array[TSCH_QUEUE_NUM_PER_NEIGHBOR]; + /* Circular buffer of pointers to packet. */ + struct ringbufindex tx_ringbuf; +}; + +/** \brief TSCH timeslot timing elements. Used to index timeslot timing + * of different units, such as rtimer tick or micro-second */ +enum tsch_timeslot_timing_elements { + tsch_ts_cca_offset, + tsch_ts_cca, + tsch_ts_tx_offset, + tsch_ts_rx_offset, + tsch_ts_rx_ack_delay, + tsch_ts_tx_ack_delay, + tsch_ts_rx_wait, + tsch_ts_ack_wait, + tsch_ts_rx_tx, + tsch_ts_max_ack, + tsch_ts_max_tx, + tsch_ts_timeslot_length, + tsch_ts_elements_count, /* Not a timing element */ +}; + +/** \brief Stores data about an incoming packet */ +struct input_packet { + uint8_t payload[TSCH_PACKET_MAX_LEN]; /* Packet payload */ + struct tsch_asn_t rx_asn; /* ASN when the packet was received */ + int len; /* Packet len */ + int16_t rssi; /* RSSI for this packet */ + uint8_t channel; /* Channel we received the packet on */ +}; + +#endif /* __TSCH_CONF_H__ */ +/** @} */ diff --git a/os/net/mac/tsch/tsch.c b/os/net/mac/tsch/tsch.c index 2ab2c6a3210b8f889f8af991771182e67ed9489f..dea750120faa091bdd42ad47861438adfb812df6 100644 --- a/os/net/mac/tsch/tsch.c +++ b/os/net/mac/tsch/tsch.c @@ -54,18 +54,9 @@ #include "net/link-stats.h" #include "net/mac/framer/framer-802154.h" #include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-slot-operation.h" -#include "net/mac/tsch/tsch-queue.h" -#include "net/mac/tsch/tsch-private.h" -#include "net/mac/tsch/tsch-log.h" -#include "net/mac/tsch/tsch-packet.h" -#include "net/mac/tsch/tsch-security.h" #include "net/mac/mac-sequence.h" #include "lib/random.h" - -#if UIP_CONF_IPV6_RPL -#include "net/mac/tsch/tsch-rpl.h" -#endif /* UIP_CONF_IPV6_RPL */ +#include "net/routing/routing.h" #if TSCH_WITH_SIXTOP #include "net/mac/tsch/sixtop/sixtop.h" @@ -275,7 +266,7 @@ keepalive_packet_sent(void *ptr, int status, int transmissions) LOG_INFO_(", st %d-%d\n", status, transmissions); /* We got no ack, try to recover by switching to the last neighbor we received an EB from */ - if(status != MAC_TX_OK) { + if(status == MAC_TX_NOACK) { if(linkaddr_cmp(&last_eb_nbr_addr, &linkaddr_null)) { LOG_WARN("not able to re-synchronize, received no EB from other neighbors\n"); if(sync_count == 0) { @@ -304,13 +295,17 @@ keepalive_send(void *ptr) { if(tsch_is_associated) { struct tsch_neighbor *n = tsch_queue_get_time_source(); - /* Simply send an empty packet */ - packetbuf_clear(); - packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &n->addr); - NETSTACK_MAC.send(keepalive_packet_sent, NULL); - LOG_INFO("sending KA to "); - LOG_INFO_LLADDR(&n->addr); - LOG_INFO_("\n"); + if(n != NULL) { + /* Simply send an empty packet */ + packetbuf_clear(); + packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &n->addr); + NETSTACK_MAC.send(keepalive_packet_sent, NULL); + LOG_INFO("sending KA to "); + LOG_INFO_LLADDR(&n->addr); + LOG_INFO_("\n"); + } else { + LOG_ERR("no timesource - KA not sent\n"); + } } } /*---------------------------------------------------------------------------*/ @@ -828,8 +823,8 @@ PROCESS_THREAD(tsch_send_eb_process, ev, data) /* Prepare the EB packet and schedule it to be sent */ if(tsch_packet_create_eb(&hdr_len, &tsch_sync_ie_offset) > 0) { struct tsch_packet *p; - /* Enqueue EB packet */ - if(!(p = tsch_queue_add_packet(&tsch_eb_address, NULL, NULL))) { + /* Enqueue EB packet, for a single transmission only */ + if(!(p = tsch_queue_add_packet(&tsch_eb_address, 1, NULL, NULL))) { LOG_ERR("! could not enqueue EB packet\n"); } else { LOG_INFO("TSCH: enqueue EB packet %u %u\n", @@ -954,6 +949,7 @@ send_packet(mac_callback_t sent, void *ptr) int ret = MAC_TX_DEFERRED; int hdr_len = 0; const linkaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); + uint8_t max_transmissions = 0; if(!tsch_is_associated) { if(!tsch_is_initialized) { @@ -1002,13 +998,19 @@ send_packet(mac_callback_t sent, void *ptr) packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr); #endif + max_transmissions = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS); + if(max_transmissions == 0) { + /* If not set by the application, use the default TSCH value */ + max_transmissions = TSCH_MAC_MAX_FRAME_RETRIES + 1; + } + if((hdr_len = NETSTACK_FRAMER.create()) < 0) { LOG_ERR("! can't send packet due to framer error\n"); ret = MAC_TX_ERR; } else { struct tsch_packet *p; /* Enqueue packet */ - p = tsch_queue_add_packet(addr, sent, ptr); + p = tsch_queue_add_packet(addr, max_transmissions, sent, ptr); if(p == NULL) { LOG_ERR("! can't send packet to "); LOG_ERR_LLADDR(addr); diff --git a/os/net/mac/tsch/tsch.h b/os/net/mac/tsch/tsch.h index 9d7661cf8d18254a59e4e4465fee058b7a79cbe7..0f108bd936b318303db35db66ed1d1ca91764047 100644 --- a/os/net/mac/tsch/tsch.h +++ b/os/net/mac/tsch/tsch.h @@ -37,6 +37,8 @@ The IEEE 802.15.4-2015 TimeSlotted Channel Hopping (TSCH) protocol. Provides scheduled communication on top of a globally-synchronized network. Performs frequency hopping for enhanced reliability. * @{ +* \file +* Main API declarations for TSCH. */ #ifndef __TSCH_H__ @@ -46,120 +48,40 @@ frequency hopping for enhanced reliability. #include "contiki.h" #include "net/mac/mac.h" +#include "net/linkaddr.h" + +#include "net/mac/tsch/tsch-conf.h" +#include "net/mac/tsch/tsch-const.h" +#include "net/mac/tsch/tsch-types.h" +#include "net/mac/tsch/tsch-adaptive-timesync.h" +#include "net/mac/tsch/tsch-slot-operation.h" +#include "net/mac/tsch/tsch-queue.h" +#include "net/mac/tsch/tsch-log.h" +#include "net/mac/tsch/tsch-packet.h" #include "net/mac/tsch/tsch-security.h" +#include "net/mac/tsch/tsch-schedule.h" +#if UIP_CONF_IPV6_RPL +#include "net/mac/tsch/tsch-rpl.h" +#endif /* UIP_CONF_IPV6_RPL */ -/******** Configuration *******/ - -/* Max time before sending a unicast keep-alive message to the time source */ -#ifdef TSCH_CONF_KEEPALIVE_TIMEOUT -#define TSCH_KEEPALIVE_TIMEOUT TSCH_CONF_KEEPALIVE_TIMEOUT -#else -/* Time to desynch assuming a drift of 40 PPM (80 PPM between two nodes) and guard time of +/-1ms: 12.5s. */ -#define TSCH_KEEPALIVE_TIMEOUT (12 * CLOCK_SECOND) -#endif - -/* With TSCH_ADAPTIVE_TIMESYNC enabled: keep-alive timeout used after reaching - * accurate drift compensation. */ -#ifdef TSCH_CONF_MAX_KEEPALIVE_TIMEOUT -#define TSCH_MAX_KEEPALIVE_TIMEOUT TSCH_CONF_MAX_KEEPALIVE_TIMEOUT -#else -#define TSCH_MAX_KEEPALIVE_TIMEOUT (60 * CLOCK_SECOND) -#endif - -/* Max time without synchronization before leaving the PAN */ -#ifdef TSCH_CONF_DESYNC_THRESHOLD -#define TSCH_DESYNC_THRESHOLD TSCH_CONF_DESYNC_THRESHOLD -#else -#define TSCH_DESYNC_THRESHOLD (2 * TSCH_MAX_KEEPALIVE_TIMEOUT) -#endif - -/* Period between two consecutive EBs */ -#ifdef TSCH_CONF_EB_PERIOD -#define TSCH_EB_PERIOD TSCH_CONF_EB_PERIOD -#else -#define TSCH_EB_PERIOD (16 * CLOCK_SECOND) -#endif - -/* Max Period between two consecutive EBs */ -#ifdef TSCH_CONF_MAX_EB_PERIOD -#define TSCH_MAX_EB_PERIOD TSCH_CONF_MAX_EB_PERIOD -#else -#define TSCH_MAX_EB_PERIOD (16 * CLOCK_SECOND) -#endif - -/* Max acceptable join priority */ -#ifdef TSCH_CONF_MAX_JOIN_PRIORITY -#define TSCH_MAX_JOIN_PRIORITY TSCH_CONF_MAX_JOIN_PRIORITY -#else -#define TSCH_MAX_JOIN_PRIORITY 32 -#endif - -/* Start TSCH automatically after init? If not, the upper layers - * must call NETSTACK_MAC.on() to start it. Useful when the - * application needs to control when the nodes are to start - * scanning or advertising.*/ -#ifdef TSCH_CONF_AUTOSTART -#define TSCH_AUTOSTART TSCH_CONF_AUTOSTART -#else -#define TSCH_AUTOSTART 1 -#endif - -/* Join only secured networks? (discard EBs with security disabled) */ -#ifdef TSCH_CONF_JOIN_SECURED_ONLY -#define TSCH_JOIN_SECURED_ONLY TSCH_CONF_JOIN_SECURED_ONLY -#else -/* By default, set if LLSEC802154_ENABLED is also non-zero */ -#define TSCH_JOIN_SECURED_ONLY LLSEC802154_ENABLED -#endif - -/* By default, join any PAN ID. Otherwise, wait for an EB from IEEE802154_PANID */ -#ifdef TSCH_CONF_JOIN_MY_PANID_ONLY -#define TSCH_JOIN_MY_PANID_ONLY TSCH_CONF_JOIN_MY_PANID_ONLY -#else -#define TSCH_JOIN_MY_PANID_ONLY 1 -#endif - -/* The radio polling frequency (in Hz) during association process */ -#ifdef TSCH_CONF_ASSOCIATION_POLL_FREQUENCY -#define TSCH_ASSOCIATION_POLL_FREQUENCY TSCH_CONF_ASSOCIATION_POLL_FREQUENCY -#else -#define TSCH_ASSOCIATION_POLL_FREQUENCY 100 -#endif - -/* When associating, check ASN against our own uptime (time in minutes).. - * Useful to force joining only with nodes started roughly at the same time. - * Set to the max number of minutes acceptable. */ -#ifdef TSCH_CONF_CHECK_TIME_AT_ASSOCIATION -#define TSCH_CHECK_TIME_AT_ASSOCIATION TSCH_CONF_CHECK_TIME_AT_ASSOCIATION -#else -#define TSCH_CHECK_TIME_AT_ASSOCIATION 0 -#endif - -/* By default: initialize schedule from EB when associating, using the - * slotframe and links Information Element */ -#ifdef TSCH_CONF_INIT_SCHEDULE_FROM_EB -#define TSCH_INIT_SCHEDULE_FROM_EB TSCH_CONF_INIT_SCHEDULE_FROM_EB -#else -#define TSCH_INIT_SCHEDULE_FROM_EB 1 -#endif +#if CONTIKI_TARGET_COOJA +#include "lib/simEnvChange.h" +#include "sys/cooja_mt.h" +#endif /* CONTIKI_TARGET_COOJA */ -/* An ad-hoc mechanism to have TSCH select its time source without the - * help of an upper-layer, simply by collecting statistics on received - * EBs and their join priority. Disabled by default as we recomment - * mapping the time source on the RPL preferred parent - * (via tsch_rpl_callback_parent_switch) */ -#ifdef TSCH_CONF_AUTOSELECT_TIME_SOURCE -#define TSCH_AUTOSELECT_TIME_SOURCE TSCH_CONF_AUTOSELECT_TIME_SOURCE -#else -#define TSCH_AUTOSELECT_TIME_SOURCE 0 -#endif /* TSCH_CONF_EB_AUTOSELECT */ +/*********** Macros *********/ -/* To include Sixtop Implementation */ -#ifdef TSCH_CONF_WITH_SIXTOP -#define TSCH_WITH_SIXTOP TSCH_CONF_WITH_SIXTOP +/* Wait for a condition with timeout t0+offset. */ +#if CONTIKI_TARGET_COOJA +#define BUSYWAIT_UNTIL_ABS(cond, t0, offset) \ + while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (offset))) { \ + simProcessRunValue = 1; \ + cooja_mt_yield(); \ + }; #else -#define TSCH_WITH_SIXTOP 0 -#endif /* TSCH_CONF_EB_AUTOSELECT */ +#define BUSYWAIT_UNTIL_ABS(cond, t0, offset) \ + while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (offset))) ; +#endif /* CONTIKI_TARGET_COOJA */ /*********** Callbacks *********/ @@ -180,6 +102,18 @@ frequency hopping for enhanced reliability. #endif /* UIP_CONF_IPV6_RPL */ +#if BUILD_WITH_ORCHESTRA + +#ifndef TSCH_CALLBACK_NEW_TIME_SOURCE +#define TSCH_CALLBACK_NEW_TIME_SOURCE orchestra_callback_new_time_source +#endif /* TSCH_CALLBACK_NEW_TIME_SOURCE */ + +#ifndef TSCH_CALLBACK_PACKET_READY +#define TSCH_CALLBACK_PACKET_READY orchestra_callback_packet_ready +#endif /* TSCH_CALLBACK_PACKET_READY */ + +#endif /* BUILD_WITH_ORCHESTRA */ + /* Called by TSCH when joining a network */ #ifdef TSCH_CALLBACK_JOINING_NETWORK void TSCH_CALLBACK_JOINING_NETWORK(); @@ -190,6 +124,28 @@ void TSCH_CALLBACK_JOINING_NETWORK(); void TSCH_CALLBACK_LEAVING_NETWORK(); #endif +/* Called by TSCH after sending a keep-alive */ +#ifdef TSCH_CALLBACK_KA_SENT +void TSCH_CALLBACK_KA_SENT(); +#endif + +/* Called by TSCH form interrupt after receiving a frame, enabled upper-layer to decide + * whether to ACK or NACK */ +#ifdef TSCH_CALLBACK_DO_NACK +int TSCH_CALLBACK_DO_NACK(struct tsch_link *link, linkaddr_t *src, linkaddr_t *dst); +#endif + +/* Called by TSCH when switching time source */ +#ifdef TSCH_CALLBACK_NEW_TIME_SOURCE +struct tsch_neighbor; +void TSCH_CALLBACK_NEW_TIME_SOURCE(const struct tsch_neighbor *old, const struct tsch_neighbor *new); +#endif + +/* Called by TSCH every time a packet is ready to be added to the send queue */ +#ifdef TSCH_CALLBACK_PACKET_READY +void TSCH_CALLBACK_PACKET_READY(void); +#endif + /***** External Variables *****/ /* Are we coordinator of the TSCH network? */ @@ -200,19 +156,84 @@ extern int tsch_is_associated; extern int tsch_is_pan_secured; /* The TSCH MAC driver */ extern const struct mac_driver tschmac_driver; +/* 802.15.4 broadcast MAC address */ +extern const linkaddr_t tsch_broadcast_address; +/* The address we use to identify EB queue */ +extern const linkaddr_t tsch_eb_address; +/* The current Absolute Slot Number (ASN) */ +extern struct tsch_asn_t tsch_current_asn; +extern uint8_t tsch_join_priority; +extern struct tsch_link *current_link; +/* TSCH channel hopping sequence */ +extern uint8_t tsch_hopping_sequence[TSCH_HOPPING_SEQUENCE_MAX_LEN]; +extern struct tsch_asn_divisor_t tsch_hopping_sequence_length; +/* TSCH timeslot timing (in rtimer ticks) */ +extern rtimer_clock_t tsch_timing[tsch_ts_elements_count]; +/* Statistics on the current session */ +extern unsigned long tx_count; +extern unsigned long rx_count; +extern unsigned long sync_count; + +/* TSCH processes */ +PROCESS_NAME(tsch_process); +PROCESS_NAME(tsch_send_eb_process); +PROCESS_NAME(tsch_pending_events_process); + /********** Functions *********/ -/* The the TSCH join priority */ +/** + * Set the TSCH join priority (JP) + * + * \param jp the new join priority + */ void tsch_set_join_priority(uint8_t jp); -/* The period at which EBs are sent */ +/** + * Set the period at wich TSCH enhanced beacons (EBs) are sent. The period can + * not be set to exceed TSCH_MAX_EB_PERIOD. Set to 0 to stop sending EBs. + * Actual transmissions are jittered, spaced by a random number within + * [period*0.75, period[ + * + * \param period The period in Clock ticks. + */ void tsch_set_eb_period(uint32_t period); -/* The keep-alive timeout */ +/** + * Set the desynchronization timeout after which a node sends a unicasst + * keep-alive (KA) to its time source. Set to 0 to stop sending KAs. The + * actual timeout is a random number within + * [timeout*0.9, timeout[ + * + * \param timeout The timeout in Clock ticks. + */ void tsch_set_ka_timeout(uint32_t timeout); -/* Set the node as PAN coordinator */ +/** + * Set the node as PAN coordinator + * + * \param enable 1 to be coordinator, 0 to be a node + */ void tsch_set_coordinator(int enable); -/* Set the pan as secured or not */ +/** + * Enable/disable security. If done at the coordinator, the Information + * will be included in EBs, and all nodes will adopt the same security level. + * Enabling requires compilation with LLSEC802154_ENABLED set. + * Note: when LLSEC802154_ENABLED is set, nodes boot with security enabled. + * + * \param enable 1 to enable security, 0 to disable it + */ void tsch_set_pan_secured(int enable); +/** + * Schedule a keep-alive transmission within [timeout*0.9, timeout[ + * @see tsch_set_ka_timeout + */ +void tsch_schedule_keepalive(void); +/** + * Schedule a keep-alive immediately + */ +void tsch_schedule_keepalive_immediately(void); +/** + * Leave the TSCH network we are currently in + */ +void tsch_disassociate(void); #endif /* __TSCH_H__ */ /** @} */ diff --git a/os/net/nbr-table.c b/os/net/nbr-table.c index f86e5954e04fc99ea1713547af7b06ca13e24c02..77d3cb07d6627d1317e5a15ef8c5b47a0b5a7ecf 100644 --- a/os/net/nbr-table.c +++ b/os/net/nbr-table.c @@ -290,6 +290,13 @@ nbr_table_register(nbr_table_t *table, nbr_table_callback *callback) ctimer_set(&periodic_timer, CLOCK_SECOND * 60, handle_periodic_timer, NULL); } #endif + + if(nbr_table_is_registered(table)) { + /* Table already registered, just update callback */ + table->callback = callback; + return 1; + } + if(num_tables < MAX_NUM_TABLES) { table->index = num_tables++; table->callback = callback; @@ -303,9 +310,10 @@ nbr_table_register(nbr_table_t *table, nbr_table_callback *callback) /*---------------------------------------------------------------------------*/ /* Test whether a specified table has been registered or not */ int -nbr_table_is_register(nbr_table_t *table) +nbr_table_is_registered(nbr_table_t *table) { - if(table != NULL && all_tables[table->index] == table) { + if(table != NULL && table->index >= 0 && table->index < MAX_NUM_TABLES + && all_tables[table->index] == table) { return 1; } return 0; @@ -490,4 +498,3 @@ handle_periodic_timer(void *ptr) ctimer_reset(&periodic_timer); } #endif - diff --git a/os/net/nbr-table.h b/os/net/nbr-table.h index 430a10a8d0e356c1de8c22f264a870bed4e693f9..d7fad52675b520f5533e6f12c04b812f7b5f0b17 100644 --- a/os/net/nbr-table.h +++ b/os/net/nbr-table.h @@ -92,7 +92,7 @@ typedef enum { /** \name Neighbor tables: register and loop through table elements */ /** @{ */ int nbr_table_register(nbr_table_t *table, nbr_table_callback *callback); -int nbr_table_is_register(nbr_table_t *table); +int nbr_table_is_registered(nbr_table_t *table); nbr_table_item_t *nbr_table_head(nbr_table_t *table); nbr_table_item_t *nbr_table_next(nbr_table_t *table, nbr_table_item_t *item); /** @} */ diff --git a/os/net/netstack.h b/os/net/netstack.h index 4251ef5e914cfaab41d370d056b96fae89a88eaf..8528e3fffe01a2b6f516b6744788bcdf3501cf6f 100644 --- a/os/net/netstack.h +++ b/os/net/netstack.h @@ -43,6 +43,22 @@ #include "contiki.h" +/* Routing protocol configuration. The Routing protocol is configured through the Makefile, + via the flag MAC_ROUTING */ +#ifdef NETSTACK_CONF_ROUTING +#define NETSTACK_ROUTING NETSTACK_CONF_ROUTING +#else /* NETSTACK_CONF_ROUTING */ +#if ROUTING_CONF_RPL_LITE +#define NETSTACK_ROUTING rpl_lite_driver +#elif ROUTING_CONF_RPL_CLASSIC +#define NETSTACK_ROUTING rpl_classic_driver +#elif ROUTING_CONF_NULLROUTING +#define NETSTACK_ROUTING nullrouting_driver +#else +#error Unknown ROUTING configuration +#endif +#endif /* NETSTACK_CONF_ROUTING */ + /* Network layer configuration. The NET layer is configured through the Makefile, via the flag MAC_NET */ #ifdef NETSTACK_CONF_NETWORK @@ -68,6 +84,8 @@ #define NETSTACK_MAC csma_driver #elif MAC_CONF_WITH_TSCH #define NETSTACK_MAC tschmac_driver +#elif MAC_CONF_WITH_BLE +#define NETSTACK_MAC ble_l2cap_driver #else #error Unknown MAC configuration #endif @@ -100,24 +118,23 @@ struct network_driver { char *name; /** Initialize the network driver */ - void (* init)(void); + void (*init)(void); /** Callback for getting notified of incoming packet in packetbuf. */ - void (* input)(void); + void (*input)(void); /** Output funtion, sends from uipbuf. */ - uint8_t (* output)(const linkaddr_t *localdest); - + uint8_t (*output)(const linkaddr_t *localdest); }; +extern const struct routing_driver NETSTACK_ROUTING; extern const struct network_driver NETSTACK_NETWORK; -extern const struct mac_driver NETSTACK_MAC; -extern const struct radio_driver NETSTACK_RADIO; -extern const struct framer NETSTACK_FRAMER; +extern const struct mac_driver NETSTACK_MAC; +extern const struct radio_driver NETSTACK_RADIO; +extern const struct framer NETSTACK_FRAMER; void netstack_init(void); - /* Netstack ip_packet_processor - for implementing packet filters, firewalls, debuggin info, etc */ @@ -133,8 +150,8 @@ enum netstack_ip_callback_type { struct netstack_ip_packet_processor { struct netstack_ip_packet_processor *next; - enum netstack_ip_action (* process_input)(void); - enum netstack_ip_action (* process_output)(const linkaddr_t *localdest); + enum netstack_ip_action (*process_input)(void); + enum netstack_ip_action (*process_output)(const linkaddr_t * localdest); }; /* This function is intended for the IP stack to call whenever input/output @@ -144,18 +161,16 @@ enum netstack_ip_action netstack_process_ip_callback(uint8_t type, const linkadd void netstack_ip_packet_processor_add(struct netstack_ip_packet_processor *p); void netstack_ip_packet_processor_remove(struct netstack_ip_packet_processor *p); - - /* Netstack sniffer - this will soon be deprecated... */ struct netstack_sniffer { struct netstack_sniffer *next; - void (* input_callback)(void); - void (* output_callback)(int mac_status); + void (*input_callback)(void); + void (*output_callback)(int mac_status); }; #define NETSTACK_SNIFFER(name, input_callback, output_callback) \ -static struct netstack_sniffer name = { NULL, input_callback, output_callback } + static struct netstack_sniffer name = { NULL, input_callback, output_callback } void netstack_sniffer_add(struct netstack_sniffer *s); void netstack_sniffer_remove(struct netstack_sniffer *s); diff --git a/os/net/packetbuf.h b/os/net/packetbuf.h index c16a3f8f1db7b0fea93b038c0e25f7be403d8acb..39ce4a4670832cdaa86c7825fe40ff2553246cba 100644 --- a/os/net/packetbuf.h +++ b/os/net/packetbuf.h @@ -217,6 +217,7 @@ enum { PACKETBUF_ATTR_LINK_QUALITY, PACKETBUF_ATTR_RSSI, PACKETBUF_ATTR_TIMESTAMP, + PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, PACKETBUF_ATTR_MAC_SEQNO, PACKETBUF_ATTR_MAC_ACK, PACKETBUF_ATTR_MAC_METADATA, diff --git a/os/net/routing/nullrouting/nullrouting.c b/os/net/routing/nullrouting/nullrouting.c new file mode 100644 index 0000000000000000000000000000000000000000..1b23d453a8776f6e546fa9666ca83c9d59fc8618 --- /dev/null +++ b/os/net/routing/nullrouting/nullrouting.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2017, RISE SICS. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \addtogroup null-routing + * @{ + * + * \file + * A routing protocol that does nothing + * + * \author Simon Duquennoy <simon.duquennoy@ri.se> + */ + +#include "net/routing/routing.h" + +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ +} +/*---------------------------------------------------------------------------*/ +static void +root_set_prefix(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) +{ +} +/*---------------------------------------------------------------------------*/ +static int +root_start(void) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +node_is_root(void) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +get_root_ipaddr(uip_ipaddr_t *ipaddr) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +get_sr_node_ipaddr(uip_ipaddr_t *addr, const uip_sr_node_t *node) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static void +leave_network(void) +{ +} +/*---------------------------------------------------------------------------*/ +static int +node_has_joined(void) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +node_is_reachable(void) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static void +global_repair(const char *str) +{ +} +/*---------------------------------------------------------------------------*/ +static void +local_repair(const char *str) +{ +} +/*---------------------------------------------------------------------------*/ +static void +ext_header_remove(void) +{ + uip_ext_len = 0; +} +/*---------------------------------------------------------------------------*/ +static int +ext_header_update(void) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +ext_header_hbh_update(int uip_ext_opt_offset) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +ext_header_srh_update(void) +{ + return 0; /* Means SRH not found */ +} +/*---------------------------------------------------------------------------*/ +static int +ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static void +link_callback(const linkaddr_t *addr, int status, int numtx) +{ +} +/*---------------------------------------------------------------------------*/ +static void +neighbor_state_changed(uip_ds6_nbr_t *nbr) +{ +} +/*---------------------------------------------------------------------------*/ +static void +drop_route(uip_ds6_route_t *route) +{ +} +/*---------------------------------------------------------------------------*/ +const struct routing_driver nullrouting_driver = { + "nullrouting", + init, + root_set_prefix, + root_start, + node_is_root, + get_root_ipaddr, + get_sr_node_ipaddr, + leave_network, + node_has_joined, + node_is_reachable, + global_repair, + local_repair, + ext_header_remove, + ext_header_update, + ext_header_hbh_update, + ext_header_srh_update, + ext_header_srh_get_next_hop, + link_callback, + neighbor_state_changed, + drop_route, +}; +/*---------------------------------------------------------------------------*/ + +/** @}*/ diff --git a/os/net/routing/routing.h b/os/net/routing/routing.h new file mode 100644 index 0000000000000000000000000000000000000000..7fe6e7ca8ea0d1603d73bf6ea3da71bf9d05e68d --- /dev/null +++ b/os/net/routing/routing.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2017, RISE SICS. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Routing driver header file + * \author + * Simon Duquennoy <simon.duquennoy@ri.se> + */ + +#ifndef ROUTING_H_ +#define ROUTING_H_ + +#include "contiki.h" +#include "net/ipv6/uip.h" +#include "net/ipv6/uip-ds6-nbr.h" +#include "net/ipv6/uip-ds6-route.h" +#include "net/ipv6/uip-sr.h" +#include "net/linkaddr.h" + +/** + * The structure of a routing protocol driver. + */ +struct routing_driver { + char *name; + /** Initialize the routing protocol */ + void (* init)(void); + /** + * Set the prefix, for nodes that will operate as root + * + * \param prefix The prefix. If NULL, UIP_DS6_DEFAULT_PREFIX is used instead + * \param iid The IID. If NULL, it will be built from uip_ds6_set_addr_iid. + */ + void (* root_set_prefix)(uip_ipaddr_t *prefix, uip_ipaddr_t *iid); + /** + * Set the node as root and start a network + * + * \return 0 in case of success, -1 otherwise + */ + int (* root_start)(void); + /** + * Tells whether the node is a network root or not + * + * \return 1 if we are root, 0 otherwise + */ + int (* node_is_root)(void); + /** + * Returns the IPv6 address of the network root, if any + * + * \param ipaddr A pointer where to copy the IP address of the root + * \return 1 if the root address was copied, 0 otherwise + */ + int (* get_root_ipaddr)(uip_ipaddr_t *ipaddr); + /** + * Returns the global IPv6 address of a source routing node + * + * \param ipaddr A pointer where to copy the IP address of the node + * \param node The source routing node + * \return 1 if the global node address was copied, 0 otherwise + */ + int (* get_sr_node_ipaddr)(uip_ipaddr_t *addr, const uip_sr_node_t *node); + /** + * Leave the network the node is part of + * + */ + void (* leave_network)(void); + /** + * Tells whether the node is currently part of a network + * + * \return 1 if we have joined a network, 0 otherwise. + */ + int (* node_has_joined)(void); + /** + * Tells whether the node is currently reachable as part of the network + * + * \return 1 if we are reachable, 0 otherwise. + */ + int (* node_is_reachable)(void); + /** + * Triggers a global topology repair + * + * \param str A textual description of the cause for triggering a repair + */ + void (* global_repair)(const char *str); + /** + * Triggers a RPL local topology repair + * + * \param str A textual description of the cause for triggering a repair + */ + void (* local_repair)(const char *str); + /** + * Removes all extension headers that pertain to the routing protocol. + */ + void (* ext_header_remove)(void); + /** + * Adds/updates routing protocol extension headers to current uIP packet. + * + * \return 1 in case of success, 0 otherwise + */ + int (* ext_header_update)(void); + /** + * Process and update the routing protocol hob-by-hop + * extention headers of the current uIP packet. + * + * \param uip_ext_opt_offset The offset within the uIP packet where + * extension headers start + * \return 1 in case the packet is valid and to be processed further, + * 0 in case the packet must be dropped. + */ + int (* ext_header_hbh_update)(int uip_ext_opt_offset); + /** + * Process and update SRH in-place, + * i.e. internal address swapping as per RFC6554 + * \return 1 if SRH found, 0 otherwise + */ + int (* ext_header_srh_update)(void); + /** + * Look for next hop from SRH of current uIP packet. + * + * \param ipaddr A pointer to the address where to store the next hop. + * \return 1 if a next hop was found, 0 otherwise + */ + int (* ext_header_srh_get_next_hop)(uip_ipaddr_t *ipaddr); + /** + * Called by lower layers after every packet transmission + * + * \param addr The link-layer addrress of the packet destination + * \param status The transmission status (see os/net/mac/mac.h) + * \param numtx The total number of transmission attempts + */ + void (* link_callback)(const linkaddr_t *addr, int status, int numtx); + /** + * Called by uIP to notify addition/removal of IPv6 neighbor entries + * + * \param addr The link-layer addrress of the packet destination + * \param status The transmission status (see os/net/mac/mac.h) + * \param numtx The total number of transmission attempts + */ + void (* neighbor_state_changed)(uip_ds6_nbr_t *nbr); + /** + * Called by uIP if it has decided to drop a route because + * + * \param route The route that will be dropped after this function returns + */ + void (* drop_route)(uip_ds6_route_t *route); +}; + +#endif /* ROUTING_H_ */ diff --git a/os/net/rpl-classic/rpl-conf.h b/os/net/routing/rpl-classic/rpl-conf.h similarity index 100% rename from os/net/rpl-classic/rpl-conf.h rename to os/net/routing/rpl-classic/rpl-conf.h diff --git a/os/net/rpl-classic/rpl-dag-root.c b/os/net/routing/rpl-classic/rpl-dag-root.c similarity index 54% rename from os/net/rpl-classic/rpl-dag-root.c rename to os/net/routing/rpl-classic/rpl-dag-root.c index 96d00f6e156309d30eb1965418d07024fba014b7..05adff4dee93ab740c1fbd9d558280325569b062 100644 --- a/os/net/rpl-classic/rpl-dag-root.c +++ b/os/net/routing/rpl-classic/rpl-dag-root.c @@ -32,9 +32,8 @@ #include "contiki.h" #include "contiki-net.h" -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" -#include "net/rpl-classic/rpl-dag-root.h" +#include "net/routing/rpl-classic/rpl.h" +#include "net/routing/rpl-classic/rpl-private.h" #include "net/ipv6/uip-ds6-route.h" #include <string.h> @@ -42,105 +41,6 @@ #define DEBUG DEBUG_NONE #include "net/ipv6/uip-debug.h" -#define RPL_DAG_GRACE_PERIOD (CLOCK_SECOND * 20 * 1) - -#if (UIP_MAX_ROUTES != 0) -static struct uip_ds6_notification n; -#endif /* (UIP_MAX_ROUTES != 0) */ -static uint8_t to_become_root; -static struct ctimer c; -/*---------------------------------------------------------------------------*/ -static const uip_ipaddr_t * -dag_root(void) -{ - rpl_dag_t *dag; - - dag = rpl_get_any_dag(); - if(dag != NULL) { - return &dag->dag_id; - } - - return NULL; -} -/*---------------------------------------------------------------------------*/ -static const uip_ipaddr_t * -get_global_address(void) -{ - int i; - uint8_t state; - uip_ipaddr_t *ipaddr = NULL; - - for(i = 0; i < UIP_DS6_ADDR_NB; i++) { - state = uip_ds6_if.addr_list[i].state; - if(uip_ds6_if.addr_list[i].isused && - state == ADDR_PREFERRED && - !uip_is_addr_linklocal(&uip_ds6_if.addr_list[i].ipaddr)) { - ipaddr = &uip_ds6_if.addr_list[i].ipaddr; - } - } - return ipaddr; -} -/*---------------------------------------------------------------------------*/ -static void -create_dag_callback(void *ptr) -{ - const uip_ipaddr_t *root, *ipaddr; - - root = dag_root(); - ipaddr = get_global_address(); - - if(root == NULL || uip_ipaddr_cmp(root, ipaddr)) { - /* The RPL network we are joining is one that we created, so we - become root. */ - if(to_become_root) { - rpl_dag_root_init_dag_immediately(); - to_become_root = 0; - } - } else { - rpl_dag_t *dag; - - dag = rpl_get_any_dag(); -#if DEBUG - printf("Found a network we did not create\n"); - printf("version %d grounded %d preference %d used %d joined %d rank %d\n", - dag->version, dag->grounded, - dag->preference, dag->used, - dag->joined, dag->rank); -#endif /* DEBUG */ - - /* We found a RPL network that we did not create so we just join - it without becoming root. But if the network has an infinite - rank, we assume the network has broken, and we become the new - root of the network. */ - - if(dag->rank == RPL_INFINITE_RANK) { - if(to_become_root) { - rpl_dag_root_init_dag_immediately(); - to_become_root = 0; - } - } - - /* Try again after the grace period */ - ctimer_set(&c, RPL_DAG_GRACE_PERIOD, create_dag_callback, NULL); - } -} -#if (UIP_MAX_ROUTES != 0) -/*---------------------------------------------------------------------------*/ -static void -route_callback(int event, uip_ipaddr_t *route, uip_ipaddr_t *ipaddr, - int numroutes) -{ - if(event == UIP_DS6_NOTIFICATION_DEFRT_ADD) { - if(route != NULL && ipaddr != NULL && - !uip_is_addr_unspecified(route) && - !uip_is_addr_unspecified(ipaddr)) { - if(to_become_root) { - ctimer_set(&c, 0, create_dag_callback, NULL); - } - } - } -} -#endif /* (UIP_MAX_ROUTES != 0) */ /*---------------------------------------------------------------------------*/ static void set_global_address(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) @@ -176,29 +76,25 @@ set_global_address(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) } /*---------------------------------------------------------------------------*/ void -rpl_dag_root_init(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) +rpl_dag_root_set_prefix(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) { static uint8_t initialized = 0; if(!initialized) { - to_become_root = 0; set_global_address(prefix, iid); -#if (UIP_MAX_ROUTES != 0) - uip_ds6_notification_add(&n, route_callback); -#endif /* (UIP_MAX_ROUTES != 0) */ initialized = 1; } } /*---------------------------------------------------------------------------*/ int -rpl_dag_root_init_dag_immediately(void) +rpl_dag_root_start(void) { struct uip_ds6_addr *root_if; int i; uint8_t state; uip_ipaddr_t *ipaddr = NULL; - rpl_dag_root_init(NULL, NULL); + rpl_dag_root_set_prefix(NULL, NULL); for(i = 0; i < UIP_DS6_ADDR_NB; i++) { state = uip_ds6_if.addr_list[i].state; @@ -223,38 +119,25 @@ rpl_dag_root_init_dag_immediately(void) if(RPL_IS_STORING(dag->instance)) { rpl_remove_routes(dag); } - if(dag->instance != NULL && - dag->instance->def_route != NULL) { - uip_ds6_defrt_rm(dag->instance->def_route); + if(dag->instance != NULL && dag->instance->def_route != NULL) { + uip_ds6_defrt_rm(dag->instance->def_route); dag->instance->def_route = NULL; } uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); rpl_set_prefix(dag, &prefix, 64); - PRINTF("rpl_dag_root_init_dag: created a new RPL dag\n"); + PRINTF("rpl_dag_root_set_prefix_dag: created a new RPL dag\n"); return 0; } else { - PRINTF("rpl_dag_root_init_dag: failed to create a new RPL DAG\n"); + PRINTF("rpl_dag_root_set_prefix_dag: failed to create a new RPL DAG\n"); return -1; } } else { - PRINTF("rpl_dag_root_init_dag: failed to create a new RPL DAG, no preferred IP address found\n"); + PRINTF("rpl_dag_root_set_prefix_dag: failed to create a new RPL DAG, no preferred IP address found\n"); return -2; } } /*---------------------------------------------------------------------------*/ -void -rpl_dag_root_init_dag_delay(void) -{ - rpl_dag_root_init(NULL, NULL); - - ctimer_set(&c, RPL_DAG_GRACE_PERIOD, create_dag_callback, NULL); - to_become_root = 1; - - /* Send a DIS packet to request RPL info from neighbors. */ - dis_output(NULL); -} -/*---------------------------------------------------------------------------*/ int rpl_dag_root_is_root(void) { diff --git a/os/net/rpl-classic/rpl-dag-root.h b/os/net/routing/rpl-classic/rpl-dag-root.h similarity index 92% rename from os/net/rpl-classic/rpl-dag-root.h rename to os/net/routing/rpl-classic/rpl-dag-root.h index 05daec15bfa80f7ddfdd39a8e7e8475638a6d813..9d2d09b02d134cc0a974955758fcc1c21180732d 100644 --- a/os/net/rpl-classic/rpl-dag-root.h +++ b/os/net/routing/rpl-classic/rpl-dag-root.h @@ -32,9 +32,8 @@ #ifndef RPL_DAG_ROOT_H_ #define RPL_DAG_ROOT_H_ -void rpl_dag_root_init(uip_ipaddr_t *prefix, uip_ipaddr_t *iid); -void rpl_dag_root_init_dag_delay(void); -int rpl_dag_root_init_dag_immediately(void); +void rpl_dag_root_set_prefix(uip_ipaddr_t *prefix, uip_ipaddr_t *iid); +int rpl_dag_root_start(void); int rpl_dag_root_is_root(void); diff --git a/os/net/rpl-classic/rpl-dag.c b/os/net/routing/rpl-classic/rpl-dag.c similarity index 96% rename from os/net/rpl-classic/rpl-dag.c rename to os/net/routing/rpl-classic/rpl-dag.c index e4f4191b1175d2b2cc30af5a0f1862e1101ec2e5..742ef16c46887278cf5220c883bd7f8b2885d779 100644 --- a/os/net/rpl-classic/rpl-dag.c +++ b/os/net/routing/rpl-classic/rpl-dag.c @@ -45,7 +45,9 @@ #include "contiki.h" #include "net/link-stats.h" -#include "net/rpl-classic/rpl-private.h" +#include "net/routing/rpl-classic/rpl.h" +#include "net/routing/rpl-classic/rpl-private.h" +#include "net/routing/rpl-classic/rpl-dag-root.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-nd6.h" #include "net/ipv6/uip-ds6-nbr.h" @@ -370,6 +372,7 @@ rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id) } if(dag == dag->instance->current_dag) { PRINTF("RPL: Dropping a joined DAG when setting this node as root"); + rpl_set_default_route(instance, NULL); dag->instance->current_dag = NULL; } else { PRINTF("RPL: Dropping a DAG when setting this node as root"); @@ -522,14 +525,16 @@ rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, unsigned len) dag->prefix_info.length = len; dag->prefix_info.flags = UIP_ND6_RA_FLAG_AUTONOMOUS; PRINTF("RPL: Prefix set - will announce this in DIOs\n"); - /* Autoconfigure an address if this node does not already have an address - with this prefix. Otherwise, update the prefix */ - if(last_len == 0) { - PRINTF("rpl_set_prefix - prefix NULL\n"); - check_prefix(NULL, &dag->prefix_info); - } else { - PRINTF("rpl_set_prefix - prefix NON-NULL\n"); - check_prefix(&last_prefix, &dag->prefix_info); + if(dag->rank != ROOT_RANK(dag->instance)) { + /* Autoconfigure an address if this node does not already have an address + with this prefix. Otherwise, update the prefix */ + if(last_len == 0) { + PRINTF("rpl_set_prefix - prefix NULL\n"); + check_prefix(NULL, &dag->prefix_info); + } else { + PRINTF("rpl_set_prefix - prefix NON-NULL\n"); + check_prefix(&last_prefix, &dag->prefix_info); + } } return 1; } @@ -665,6 +670,10 @@ rpl_free_dag(rpl_dag_t *dag) if(RPL_IS_STORING(dag->instance)) { rpl_remove_routes(dag); } + /* Stop the DAO retransmit timer */ +#if RPL_WITH_DAO_ACK + ctimer_stop(&dag->instance->dao_retransmit_timer); +#endif /* RPL_WITH_DAO_ACK */ /* Remove autoconfigured address */ if((dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS)) { @@ -757,22 +766,17 @@ rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p) old_rank = instance->current_dag->rank; last_parent = instance->current_dag->preferred_parent; - best_dag = instance->current_dag; - if(best_dag->rank != ROOT_RANK(instance)) { - if(rpl_select_parent(p->dag) != NULL) { - if(p->dag != best_dag) { - best_dag = instance->of->best_dag(best_dag, p->dag); - } - } else if(p->dag == best_dag) { - best_dag = NULL; - for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) { - if(dag->used && dag->preferred_parent != NULL && dag->preferred_parent->rank != RPL_INFINITE_RANK) { - if(best_dag == NULL) { - best_dag = dag; - } else { - best_dag = instance->of->best_dag(best_dag, dag); - } - } + if(instance->current_dag->rank != ROOT_RANK(instance)) { + rpl_select_parent(p->dag); + } + + best_dag = NULL; + for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) { + if(dag->used && dag->preferred_parent != NULL && dag->preferred_parent->rank != RPL_INFINITE_RANK) { + if(best_dag == NULL) { + best_dag = dag; + } else { + best_dag = instance->of->best_dag(best_dag, dag); } } } @@ -825,7 +829,7 @@ rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p) if(best_dag->preferred_parent != last_parent) { rpl_set_default_route(instance, rpl_parent_get_ipaddr(best_dag->preferred_parent)); PRINTF("RPL: Changed preferred parent, rank changed from %u to %u\n", - (unsigned)old_rank, best_dag->rank); + (unsigned)old_rank, best_dag->rank); RPL_STAT(rpl_stats.parent_switch++); if(RPL_IS_STORING(instance)) { if(last_parent != NULL) { @@ -844,7 +848,7 @@ rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p) #endif } else if(best_dag->rank != old_rank) { PRINTF("RPL: Preferred parent update, rank changed from %u to %u\n", - (unsigned)old_rank, best_dag->rank); + (unsigned)old_rank, best_dag->rank); } return best_dag; } @@ -1002,9 +1006,18 @@ rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent) } /*---------------------------------------------------------------------------*/ int +rpl_has_joined(void) +{ + return rpl_get_any_dag() != NULL; +} +/*---------------------------------------------------------------------------*/ +int rpl_has_downward_route(void) { int i; + if(rpl_dag_root_is_root()) { + return 1; /* We are the root, and know the route to ourself */ + } for(i = 0; i < RPL_MAX_INSTANCES; ++i) { if(instance_table[i].used && instance_table[i].has_downward_route) { return 1; @@ -1323,6 +1336,9 @@ rpl_local_repair(rpl_instance_t *instance) /* no downward route anymore */ instance->has_downward_route = 0; +#if RPL_WITH_DAO_ACK + ctimer_stop(&instance->dao_retransmit_timer); +#endif /* RPL_WITH_DAO_ACK */ rpl_reset_dio_timer(instance); if(RPL_IS_STORING(instance)) { diff --git a/os/net/rpl-classic/rpl-ext-header.c b/os/net/routing/rpl-classic/rpl-ext-header.c similarity index 92% rename from os/net/rpl-classic/rpl-ext-header.c rename to os/net/routing/rpl-classic/rpl-ext-header.c index 0c1f8076a2f08db8406c3f6b6e838df1d0b94d42..e6498b99397d9447d2008935c0917ab20b360566 100644 --- a/os/net/rpl-classic/rpl-ext-header.c +++ b/os/net/routing/rpl-classic/rpl-ext-header.c @@ -44,11 +44,12 @@ * @{ */ +#include "net/routing/routing.h" #include "net/ipv6/uip.h" #include "net/ipv6/tcpip.h" #include "net/ipv6/uip-ds6.h" -#include "net/rpl-classic/rpl-private.h" -#include "net/rpl-classic/rpl-ns.h" +#include "net/ipv6/uip-sr.h" +#include "net/routing/rpl-classic/rpl-private.h" #include "net/packetbuf.h" #define DEBUG DEBUG_NONE @@ -174,15 +175,15 @@ rpl_ext_header_hbh_update(int uip_ext_opt_offset) return 1; } /*---------------------------------------------------------------------------*/ -#if RPL_WITH_NON_STORING int rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr) { +#if RPL_WITH_NON_STORING uint8_t *uip_next_hdr; int last_uip_ext_len = uip_ext_len; rpl_dag_t *dag; - rpl_ns_node_t *dest_node; - rpl_ns_node_t *root_node; + uip_sr_node_t *dest_node; + uip_sr_node_t *root_node; uip_ext_len = 0; uip_next_hdr = &UIP_IP_BUF->proto; @@ -208,8 +209,8 @@ rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr) } dag = rpl_get_dag(&UIP_IP_BUF->destipaddr); - root_node = rpl_ns_get_node(dag, &dag->dag_id); - dest_node = rpl_ns_get_node(dag, &UIP_IP_BUF->destipaddr); + root_node = uip_sr_get_node(dag, &dag->dag_id); + dest_node = uip_sr_get_node(dag, &UIP_IP_BUF->destipaddr); if((uip_next_hdr != NULL && *uip_next_hdr == UIP_PROTO_ROUTING && UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) || @@ -227,11 +228,15 @@ rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr) uip_ext_len = last_uip_ext_len; return 0; +#else /* RPL_WITH_NON_STORING */ + return 0; /* SRH not found */ +#endif /* RPL_WITH_NON_STORING */ } /*---------------------------------------------------------------------------*/ int rpl_ext_header_srh_update(void) { +#if RPL_WITH_NON_STORING uint8_t *uip_next_hdr; int last_uip_ext_len = uip_ext_len; @@ -308,6 +313,9 @@ rpl_ext_header_srh_update(void) uip_ext_len = last_uip_ext_len; return 0; +#else /* RPL_WITH_NON_STORING */ + return 0; /* SRH not found */ +#endif /* RPL_WITH_NON_STORING */ } /*---------------------------------------------------------------------------*/ static int @@ -332,9 +340,9 @@ insert_srh_header(void) uint8_t cmpri, cmpre; /* ComprI and ComprE fields of the RPL Source Routing Header */ uint8_t *hop_ptr; uint8_t padding; - rpl_ns_node_t *dest_node; - rpl_ns_node_t *root_node; - rpl_ns_node_t *node; + uip_sr_node_t *dest_node; + uip_sr_node_t *root_node; + uip_sr_node_t *node; rpl_dag_t *dag; uip_ipaddr_t node_addr; @@ -352,19 +360,19 @@ insert_srh_header(void) return 0; } - dest_node = rpl_ns_get_node(dag, &UIP_IP_BUF->destipaddr); + dest_node = uip_sr_get_node(dag, &UIP_IP_BUF->destipaddr); if(dest_node == NULL) { /* The destination is not found, skip SRH insertion */ return 1; } - root_node = rpl_ns_get_node(dag, &dag->dag_id); + root_node = uip_sr_get_node(dag, &dag->dag_id); if(root_node == NULL) { PRINTF("RPL: SRH root node not found\n"); return 0; } - if(!rpl_ns_is_node_reachable(dag, &UIP_IP_BUF->destipaddr)) { + if(!uip_sr_is_addr_reachable(dag, &UIP_IP_BUF->destipaddr)) { PRINTF("RPL: SRH no path found to destination\n"); return 0; } @@ -383,7 +391,7 @@ insert_srh_header(void) while(node != NULL && node != root_node) { - rpl_ns_get_node_global_addr(&node_addr, node); + NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node); /* How many bytes in common between all nodes in the path? */ cmpri = MIN(cmpri, count_matching_bytes(&node_addr, &UIP_IP_BUF->destipaddr, 16)); @@ -408,7 +416,7 @@ insert_srh_header(void) path_len, cmpri, cmpre, ext_len, padding); /* Check if there is enough space to store the extension header */ - if(uip_len + ext_len > UIP_BUFSIZE) { + if(uip_len + ext_len > UIP_BUFSIZE - UIP_LLH_LEN) { PRINTF("RPL: Packet too long: impossible to add source routing header (%u bytes)\n", ext_len); return 0; } @@ -437,7 +445,7 @@ insert_srh_header(void) hop_ptr = ((uint8_t *)UIP_RH_BUF) + ext_len - padding; /* Pointer where to write the next hop compressed address */ while(node != NULL && node->parent != root_node) { - rpl_ns_get_node_global_addr(&node_addr, node); + NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node); hop_ptr -= (16 - cmpri); memcpy(hop_ptr, ((uint8_t*)&node_addr) + cmpri, 16 - cmpri); @@ -446,7 +454,7 @@ insert_srh_header(void) } /* The next hop (i.e. node whose parent is the root) is placed as the current IPv6 destination */ - rpl_ns_get_node_global_addr(&node_addr, node); + NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node); uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &node_addr); /* In-place update of IPv6 length field */ @@ -461,9 +469,6 @@ insert_srh_header(void) return 1; } -#else /* RPL_WITH_NON_STORING */ -int insert_srh_header(void); -#endif /* RPL_WITH_NON_STORING */ /*---------------------------------------------------------------------------*/ static int update_hbh_header(void) @@ -553,7 +558,7 @@ insert_hbh_header(const rpl_instance_t *instance) /* Insert hop-by-hop header */ PRINTF("RPL: Creating hop-by-hop option\n"); - if(uip_len + RPL_HOP_BY_HOP_LEN > UIP_BUFSIZE) { + if(uip_len + RPL_HOP_BY_HOP_LEN > UIP_BUFSIZE - UIP_LLH_LEN) { PRINTF("RPL: Packet too long: impossible to add hop-by-hop option\n"); uip_ext_len = last_uip_ext_len; return 0; @@ -592,9 +597,11 @@ rpl_ext_header_remove(void) { uint8_t temp_len; uint8_t rpl_ext_hdr_len; + int uip_ext_opt_offset; uint8_t *uip_next_hdr; uip_ext_len = 0; + uip_ext_opt_offset = 2; uip_next_hdr = &UIP_IP_BUF->proto; /* Look for hop-by-hop and routing headers */ @@ -602,17 +609,22 @@ rpl_ext_header_remove(void) switch(*uip_next_hdr) { case UIP_PROTO_HBHO: case UIP_PROTO_ROUTING: - /* Remove hop-by-hop and routing headers */ - *uip_next_hdr = UIP_EXT_BUF->next; - rpl_ext_hdr_len = (UIP_EXT_BUF->len * 8) + 8; - temp_len = UIP_IP_BUF->len[1]; - uip_len -= rpl_ext_hdr_len; - UIP_IP_BUF->len[1] -= rpl_ext_hdr_len; - if(UIP_IP_BUF->len[1] > temp_len) { - UIP_IP_BUF->len[0]--; + if((*uip_next_hdr != UIP_PROTO_HBHO || UIP_EXT_HDR_OPT_RPL_BUF->opt_type == UIP_EXT_HDR_OPT_RPL)) { + /* Remove hop-by-hop and routing headers */ + *uip_next_hdr = UIP_EXT_BUF->next; + rpl_ext_hdr_len = (UIP_EXT_BUF->len * 8) + 8; + temp_len = UIP_IP_BUF->len[1]; + uip_len -= rpl_ext_hdr_len; + UIP_IP_BUF->len[1] -= rpl_ext_hdr_len; + if(UIP_IP_BUF->len[1] > temp_len) { + UIP_IP_BUF->len[0]--; + } + PRINTF("RPL: Removing RPL extension header (type %u, len %u)\n", *uip_next_hdr, rpl_ext_hdr_len); + memmove(UIP_EXT_BUF, ((uint8_t *)UIP_EXT_BUF) + rpl_ext_hdr_len, uip_len - UIP_IPH_LEN); + } else { + uip_next_hdr = &UIP_EXT_BUF->next; + uip_ext_len += (UIP_EXT_BUF->len << 3) + 8; } - PRINTF("RPL: Removing RPL extension header (type %u, len %u)\n", *uip_next_hdr, rpl_ext_hdr_len); - memmove(UIP_EXT_BUF, ((uint8_t *)UIP_EXT_BUF) + rpl_ext_hdr_len, uip_len - UIP_IPH_LEN); break; case UIP_PROTO_DESTO: /* @@ -626,6 +638,7 @@ rpl_ext_header_remove(void) /* Move to next header */ uip_next_hdr = &UIP_EXT_BUF->next; uip_ext_len += (UIP_EXT_BUF->len << 3) + 8; + break; default: return; } diff --git a/os/net/rpl-classic/rpl-icmp6.c b/os/net/routing/rpl-classic/rpl-icmp6.c similarity index 97% rename from os/net/rpl-classic/rpl-icmp6.c rename to os/net/routing/rpl-classic/rpl-icmp6.c index 6da3c265682473abde5805b79ede502cb3938de2..914575dbfe6051e89fa0ff78d24830621dd44ce8 100644 --- a/os/net/rpl-classic/rpl-icmp6.c +++ b/os/net/routing/rpl-classic/rpl-icmp6.c @@ -49,9 +49,9 @@ #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip-nd6.h" +#include "net/ipv6/uip-sr.h" #include "net/ipv6/uip-icmp6.h" -#include "net/rpl-classic/rpl-private.h" -#include "net/rpl-classic/rpl-ns.h" +#include "net/routing/rpl-classic/rpl-private.h" #include "net/packetbuf.h" #include "net/ipv6/multicast/uip-mcast6.h" #include "random.h" @@ -141,15 +141,23 @@ get_global_addr(uip_ipaddr_t *addr) { int i; int state; + uip_ipaddr_t *prefix = NULL; + uint8_t prefix_length = 0; + rpl_dag_t *dag = rpl_get_any_dag(); + + if(dag != NULL && dag->prefix_info.length != 0) { + prefix = &dag->prefix_info.prefix; + prefix_length = dag->prefix_info.length; + } for(i = 0; i < UIP_DS6_ADDR_NB; i++) { state = uip_ds6_if.addr_list[i].state; if(uip_ds6_if.addr_list[i].isused && - (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { - if(!uip_is_addr_linklocal(&uip_ds6_if.addr_list[i].ipaddr)) { - memcpy(addr, &uip_ds6_if.addr_list[i].ipaddr, sizeof(uip_ipaddr_t)); - return 1; - } + state == ADDR_PREFERRED && + !uip_is_addr_linklocal(&uip_ds6_if.addr_list[i].ipaddr) && + (prefix == NULL || uip_ipaddr_prefixcmp(prefix, &uip_ds6_if.addr_list[i].ipaddr, prefix_length))) { + memcpy(addr, &uip_ds6_if.addr_list[i].ipaddr, sizeof(uip_ipaddr_t)); + return 1; } } return 0; @@ -985,9 +993,9 @@ dao_input_nonstoring(void) if(lifetime == RPL_ZERO_LIFETIME) { PRINTF("RPL: No-Path DAO received\n"); - rpl_ns_expire_parent(dag, &prefix, &dao_parent_addr); + uip_sr_expire_parent(dag, &prefix, &dao_parent_addr); } else { - if(rpl_ns_update_node(dag, &prefix, &dao_parent_addr, RPL_LIFETIME(instance, lifetime)) == NULL) { + if(uip_sr_update_node(dag, &prefix, &dao_parent_addr, RPL_LIFETIME(instance, lifetime)) == NULL) { PRINTF("RPL: failed to add link\n"); return; } @@ -1282,6 +1290,12 @@ dao_ack_input(void) parent = NULL; } + if(instance->current_dag->rank == ROOT_RANK(instance)) { + PRINTF("RPL: DODAG root received a DAO ACK, ignoring it\n"); + uip_clear_buf(); + return; + } + PRINTF("RPL: Received a DAO %s with sequence number %d (%d) and status %d from ", status < 128 ? "ACK" : "NACK", sequence, instance->my_dao_seqno, status); diff --git a/os/net/rpl-classic/rpl-mrhof.c b/os/net/routing/rpl-classic/rpl-mrhof.c similarity index 93% rename from os/net/rpl-classic/rpl-mrhof.c rename to os/net/routing/rpl-classic/rpl-mrhof.c index 21db377e70727df8398d5fc49a4092a698071f58..f3c75985b8cab1c7068a9dff742e27d432257cce 100644 --- a/os/net/rpl-classic/rpl-mrhof.c +++ b/os/net/routing/rpl-classic/rpl-mrhof.c @@ -46,8 +46,8 @@ * @{ */ -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" +#include "net/routing/rpl-classic/rpl.h" +#include "net/routing/rpl-classic/rpl-private.h" #include "net/nbr-table.h" #include "net/link-stats.h" @@ -56,14 +56,19 @@ /* RFC6551 and RFC6719 do not mandate the use of a specific formula to * compute the ETX value. This MRHOF implementation relies on the value - * computed by the link-stats module. It has an optional feature, + * computed by the link-stats module.It has an optional feature, * RPL_MRHOF_CONF_SQUARED_ETX, that consists in squaring this value. - * This basically penalizes bad links while preserving the semantics of ETX + * + * Squaring basically penalizes bad links while preserving the semantics of ETX * (1 = perfect link, more = worse link). As a result, MRHOF will favor - * good links over short paths. Recommended when reliability is a priority. - * Without this feature, a hop with 50% PRR (ETX=2) is equivalent to two - * perfect hops with 100% PRR (ETX=1+1=2). With this feature, the former - * path obtains ETX=2*2=4 and the former ETX=1*1+1*1=2. */ + * good links over short paths. Without this feature, a hop with 50% PRR (ETX=2) + * is equivalent to two perfect hops with 100% PRR (ETX=1+1=2). With this + * feature, the former path obtains ETX=2*2=4 and the former ETX=1*1+1*1=2. + * + * While this feature helps achieve extra relaibility, it also results in + * added churn. In networks with high congestion or poor links, this can lead + * to poor connectivity due to more parent switches, loops, Trickle resets, etc. + */ #ifdef RPL_MRHOF_CONF_SQUARED_ETX #define RPL_MRHOF_SQUARED_ETX RPL_MRHOF_CONF_SQUARED_ETX #else /* RPL_MRHOF_CONF_SQUARED_ETX */ diff --git a/os/net/rpl-classic/rpl-nbr-policy.c b/os/net/routing/rpl-classic/rpl-nbr-policy.c similarity index 99% rename from os/net/rpl-classic/rpl-nbr-policy.c rename to os/net/routing/rpl-classic/rpl-nbr-policy.c index 1804fd4b734db8499e95940ee143a69275e1e670..077977a100c0405f4cad38f81c311fa323cb3ab1 100644 --- a/os/net/rpl-classic/rpl-nbr-policy.c +++ b/os/net/routing/rpl-classic/rpl-nbr-policy.c @@ -44,7 +44,7 @@ * */ -#include "net/rpl-classic/rpl-private.h" +#include "net/routing/rpl-classic/rpl-private.h" #include "net/nbr-table.h" #include "net/ipv6/uip-ds6-nbr.h" #include "net/ipv6/uip-ds6-route.h" diff --git a/os/net/rpl-classic/rpl-of0.c b/os/net/routing/rpl-classic/rpl-of0.c similarity index 98% rename from os/net/rpl-classic/rpl-of0.c rename to os/net/routing/rpl-classic/rpl-of0.c index aa18823cb5171b7b7bf193c4a7a6d1a9bd2a1ffb..1a679d23b98372aef53e72dd6ce160de51c3f662 100644 --- a/os/net/rpl-classic/rpl-of0.c +++ b/os/net/routing/rpl-classic/rpl-of0.c @@ -42,8 +42,8 @@ * @{ */ -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" +#include "net/routing/rpl-classic/rpl.h" +#include "net/routing/rpl-classic/rpl-private.h" #include "net/nbr-table.h" #include "net/link-stats.h" diff --git a/os/net/rpl-classic/rpl-private.h b/os/net/routing/rpl-classic/rpl-private.h similarity index 98% rename from os/net/rpl-classic/rpl-private.h rename to os/net/routing/rpl-classic/rpl-private.h index f00734821aef8a378e75e49e15d8ddeb50692931..1259fffeb6e33d5562e5d726ac7f382a65edaeb1 100644 --- a/os/net/rpl-classic/rpl-private.h +++ b/os/net/routing/rpl-classic/rpl-private.h @@ -37,7 +37,7 @@ #ifndef RPL_PRIVATE_H #define RPL_PRIVATE_H -#include "net/rpl-classic/rpl.h" +#include "net/routing/rpl-classic/rpl.h" #include "lib/list.h" #include "net/ipv6/uip.h" @@ -45,7 +45,6 @@ #include "sys/ctimer.h" #include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip-ds6-route.h" -#include "net/rpl-classic/rpl-ns.h" #include "net/ipv6/multicast/uip-mcast6.h" /*---------------------------------------------------------------------------*/ @@ -199,13 +198,6 @@ #define RPL_ROUTE_FROM_MULTICAST_DAO 2 #define RPL_ROUTE_FROM_DIO 3 -/* Multicast Route Lifetime as a multiple of the lifetime unit */ -#ifdef RPL_CONF_MCAST_LIFETIME -#define RPL_MCAST_LIFETIME RPL_CONF_MCAST_LIFETIME -#else -#define RPL_MCAST_LIFETIME 3 -#endif - /* DIS related */ #define RPL_DIS_SEND 1 diff --git a/os/net/rpl-classic/rpl-timers.c b/os/net/routing/rpl-classic/rpl-timers.c similarity index 95% rename from os/net/rpl-classic/rpl-timers.c rename to os/net/routing/rpl-classic/rpl-timers.c index b89a1258dbc62b5abed8bad2c332bcd19fb291bf..c812a8897c09a4757a2ce04c5f32b09c23de7a20 100644 --- a/os/net/rpl-classic/rpl-timers.c +++ b/os/net/routing/rpl-classic/rpl-timers.c @@ -42,10 +42,10 @@ */ #include "contiki.h" -#include "net/rpl-classic/rpl-private.h" -#include "net/rpl-classic/rpl-ns.h" +#include "net/routing/rpl-classic/rpl-private.h" #include "net/link-stats.h" #include "net/ipv6/multicast/uip-mcast6.h" +#include "net/ipv6/uip-sr.h" #include "lib/random.h" #include "sys/ctimer.h" @@ -89,7 +89,7 @@ handle_periodic_timer(void *ptr) rpl_purge_routes(); } if(RPL_IS_NON_STORING(dag->instance)) { - rpl_ns_periodic(); + uip_sr_periodic(1); } } rpl_recalculate_ranks(); @@ -283,7 +283,7 @@ handle_dao_timer(void *ptr) if(uip_ds6_if.maddr_list[i].isused && uip_is_addr_mcast_global(&uip_ds6_if.maddr_list[i].ipaddr)) { dao_output_target(instance->current_dag->preferred_parent, - &uip_ds6_if.maddr_list[i].ipaddr, RPL_MCAST_LIFETIME); + &uip_ds6_if.maddr_list[i].ipaddr, instance->default_lifetime); } } @@ -293,7 +293,7 @@ handle_dao_timer(void *ptr) /* Don't send if it's also our own address, done that already */ if(uip_ds6_maddr_lookup(&mcast_route->group) == NULL) { dao_output_target(instance->current_dag->preferred_parent, - &mcast_route->group, RPL_MCAST_LIFETIME); + &mcast_route->group, instance->default_lifetime); } mcast_route = list_item_next(mcast_route); } @@ -457,11 +457,29 @@ get_probing_target(rpl_dag_t *dag) return probing_target; } /*---------------------------------------------------------------------------*/ +static rpl_dag_t * +get_next_dag(rpl_instance_t *instance) +{ + rpl_dag_t *dag = NULL; + int new_dag = instance->last_dag; + do { + new_dag++; + if(new_dag >= RPL_MAX_DAG_PER_INSTANCE) { + new_dag = 0; + } + if(instance->dag_table[new_dag].used) { + dag = &instance->dag_table[new_dag]; + } + } while(new_dag != instance->last_dag && dag == NULL); + instance->last_dag = new_dag; + return dag; +} +/*---------------------------------------------------------------------------*/ static void handle_probing_timer(void *ptr) { rpl_instance_t *instance = (rpl_instance_t *)ptr; - rpl_parent_t *probing_target = RPL_PROBING_SELECT_FUNC(instance->current_dag); + rpl_parent_t *probing_target = RPL_PROBING_SELECT_FUNC(get_next_dag(instance)); uip_ipaddr_t *target_ipaddr = rpl_parent_get_ipaddr(probing_target); /* Perform probing */ diff --git a/os/net/rpl-classic/rpl.c b/os/net/routing/rpl-classic/rpl.c similarity index 80% rename from os/net/rpl-classic/rpl.c rename to os/net/routing/rpl-classic/rpl.c index dfa7c99cf688aa6069fd55a2bbd5826b53452315..b1905d61153031e14e7a3e74ff80547beda4b13c 100644 --- a/os/net/rpl-classic/rpl.c +++ b/os/net/routing/rpl-classic/rpl.c @@ -45,9 +45,11 @@ #include "net/ipv6/uip.h" #include "net/ipv6/tcpip.h" #include "net/ipv6/uip-ds6.h" +#include "net/ipv6/uip-sr.h" #include "net/ipv6/uip-icmp6.h" -#include "net/rpl-classic/rpl-private.h" -#include "net/rpl-classic/rpl-ns.h" +#include "net/routing/routing.h" +#include "net/routing/rpl-classic/rpl-private.h" +#include "net/routing/rpl-classic/rpl-dag-root.h" #include "net/ipv6/multicast/uip-mcast6.h" #define DEBUG DEBUG_NONE @@ -327,8 +329,8 @@ rpl_purge_dags(void) } } /*---------------------------------------------------------------------------*/ -void -rpl_init(void) +static void +init(void) { uip_ipaddr_t rplmaddr; PRINTF("RPL started\n"); @@ -347,9 +349,93 @@ rpl_init(void) #endif #if RPL_WITH_NON_STORING - rpl_ns_init(); + uip_sr_init(); #endif /* RPL_WITH_NON_STORING */ } /*---------------------------------------------------------------------------*/ +static int +get_sr_node_ipaddr(uip_ipaddr_t *addr, const uip_sr_node_t *node) +{ + if(addr != NULL && node != NULL) { + memcpy(addr, &((rpl_dag_t *)node->graph)->dag_id, 8); + memcpy(((unsigned char *)addr) + 8, &node->link_identifier, 8); + return 1; + } else { + return 0; + } +} +/*---------------------------------------------------------------------------*/ +static void +global_repair(const char *str) +{ + rpl_dag_t *dag = rpl_get_any_dag(); + if(dag != NULL && dag->instance != NULL) { + rpl_repair_root(dag->instance->instance_id); + } +} +/*---------------------------------------------------------------------------*/ +static void +local_repair(const char *str) +{ + rpl_dag_t *dag = rpl_get_any_dag(); + if(dag != NULL) { + rpl_local_repair(dag->instance); + } +} +/*---------------------------------------------------------------------------*/ +static void +drop_route(uip_ds6_route_t *route) +{ + /* If we are the root of the network, trigger a global repair before + the route gets removed */ + rpl_dag_t *dag; + dag = (rpl_dag_t *)route->state.dag; + if(dag != NULL && dag->instance != NULL) { + rpl_repair_root(dag->instance->instance_id); + } +} +/*---------------------------------------------------------------------------*/ +static void +leave_network(void) +{ + PRINTF("RPL: leave_network not supported in RPL Classic\n"); +} +/*---------------------------------------------------------------------------*/ +static int +get_root_ipaddr(uip_ipaddr_t *ipaddr) +{ + rpl_dag_t *dag; + /* Use the DAG id as server address if no other has been specified */ + dag = rpl_get_any_dag(); + if(dag != NULL && ipaddr != NULL) { + uip_ipaddr_copy(ipaddr, &dag->dag_id); + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +const struct routing_driver rpl_classic_driver = { + "RPL Classic", + init, + rpl_dag_root_set_prefix, + rpl_dag_root_start, + rpl_dag_root_is_root, + get_root_ipaddr, + get_sr_node_ipaddr, + leave_network, + rpl_has_joined, + rpl_has_downward_route, + global_repair, + local_repair, + rpl_ext_header_remove, + rpl_ext_header_update, + rpl_ext_header_hbh_update, + rpl_ext_header_srh_update, + rpl_ext_header_srh_get_next_hop, + rpl_link_callback, + rpl_ipv6_neighbor_callback, + drop_route, +}; +/*---------------------------------------------------------------------------*/ /** @}*/ diff --git a/os/net/rpl-classic/rpl.h b/os/net/routing/rpl-classic/rpl.h similarity index 98% rename from os/net/rpl-classic/rpl.h rename to os/net/routing/rpl-classic/rpl.h index 185bcbef2debf73e9b80ebaacff548ea520d883a..db87cc8246d868b2402bcf7cbe6d58b5f57326b8 100644 --- a/os/net/rpl-classic/rpl.h +++ b/os/net/routing/rpl-classic/rpl.h @@ -38,7 +38,7 @@ #ifndef RPL_H #define RPL_H -#include "net/rpl-classic/rpl-conf.h" +#include "net/routing/rpl-classic/rpl-conf.h" #include "lib/list.h" #include "net/ipv6/uip.h" @@ -252,6 +252,7 @@ struct rpl_instance { #if RPL_WITH_PROBING struct ctimer probing_timer; rpl_parent_t *urgent_probing_target; + int last_dag; #endif /* RPL_WITH_PROBING */ struct ctimer dio_timer; struct ctimer dao_timer; @@ -265,7 +266,6 @@ struct rpl_instance { /*---------------------------------------------------------------------------*/ /* Public RPL functions. */ -void rpl_init(void); void uip_rpl_input(void); rpl_dag_t *rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id); int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, unsigned len); @@ -327,6 +327,12 @@ enum rpl_mode rpl_set_mode(enum rpl_mode mode); */ enum rpl_mode rpl_get_mode(void); +/** + * Tells whether the node has joined a network or not + * + * \retval 1 if we have joined a network, 0 if not. + */ +int rpl_has_joined(void); /** * Get the RPL's best guess on if we have downward route or not. diff --git a/os/net/rpl-lite/rpl-conf.h b/os/net/routing/rpl-lite/rpl-conf.h similarity index 95% rename from os/net/rpl-lite/rpl-conf.h rename to os/net/routing/rpl-lite/rpl-conf.h index 6ada97f0b56bb278450c42a15711da4afce89017..a3693f8b951ac955176894f5656a8e227e66648b 100644 --- a/os/net/rpl-lite/rpl-conf.h +++ b/os/net/routing/rpl-lite/rpl-conf.h @@ -28,6 +28,9 @@ * * This file is part of the Contiki operating system. * + */ + +/** * \addtogroup rpl-lite * @{ * @@ -59,18 +62,16 @@ * We only support non-storing mode */ #define RPL_WITH_STORING 0 -#define RPL_WITH_NON_STORING (RPL_MOP_DEFAULT == RPL_MOP_NON_STORING) -/* The number of non-storing nodes, i.e. the maximum netwrok size at the root */ -#ifdef RPL_NS_CONF_LINK_NUM -#define RPL_NS_LINK_NUM RPL_NS_CONF_LINK_NUM -#else /* RPL_NS_CONF_LINK_NUM */ -#if RPL_WITH_NON_STORING -#define RPL_NS_LINK_NUM NETSTACK_MAX_ROUTE_ENTRIES -#else -#define RPL_NS_LINK_NUM 0 -#endif -#endif /* RPL_NS_CONF_LINK_NUM */ +/* + * Embed support for non-storing mode + */ +#ifdef RPL_CONF_WITH_NON_STORING +#define RPL_WITH_NON_STORING RPL_CONF_WITH_NON_STORING +#else /* RPL_CONF_WITH_NON_STORING */ +/* By default: embed support for non-storing if and only if the configured MOP is non-storing */ +#define RPL_WITH_NON_STORING (RPL_MOP_DEFAULT == RPL_MOP_NON_STORING) +#endif /* RPL_CONF_WITH_NON_STORING */ /* * The objective function (OF) used by a RPL root is configurable through @@ -306,13 +307,6 @@ #define RPL_DAO_DELAY (CLOCK_SECOND * 4) #endif /* RPL_CONF_DAO_DELAY */ -/* Delay between reception of a no-path DAO and actual route removal */ -#ifdef RPL_CONF_NOPATH_REMOVAL_DELAY -#define RPL_NOPATH_REMOVAL_DELAY RPL_CONF_NOPATH_REMOVAL_DELAY -#else /* RPL_CONF_NOPATH_REMOVAL_DELAY */ -#define RPL_NOPATH_REMOVAL_DELAY 60 -#endif /* RPL_CONF_NOPATH_REMOVAL_DELAY */ - #ifdef RPL_CONF_DAO_MAX_RETRANSMISSIONS #define RPL_DAO_MAX_RETRANSMISSIONS RPL_CONF_DAO_MAX_RETRANSMISSIONS #else diff --git a/os/net/rpl-lite/rpl-const.h b/os/net/routing/rpl-lite/rpl-const.h similarity index 99% rename from os/net/rpl-lite/rpl-const.h rename to os/net/routing/rpl-lite/rpl-const.h index 4bf6c1e4f0c64a8332160a5cc3e7fb2aabb36014..efeabd1f12f787041ea3dee3f3b32000a604f77d 100644 --- a/os/net/rpl-lite/rpl-const.h +++ b/os/net/routing/rpl-lite/rpl-const.h @@ -28,6 +28,9 @@ * * This file is part of the Contiki operating system. * + */ + +/** * \addtogroup rpl-lite * @{ * @@ -42,11 +45,6 @@ #ifndef RPL_CONST_H #define RPL_CONST_H -/** - * \addtogroup rpl-lite - * @{ - */ - /********** Constants **********/ /* Special value indicating infinite lifetime. */ diff --git a/os/net/rpl-lite/rpl-dag-root.c b/os/net/routing/rpl-lite/rpl-dag-root.c similarity index 68% rename from os/net/rpl-lite/rpl-dag-root.c rename to os/net/routing/rpl-lite/rpl-dag-root.c index cfe227d4c22a1f3d1ae1522c4cf4347a8cebeecd..0d5cebe92b3ec9f67e43634d16dc93163ab93188 100644 --- a/os/net/rpl-lite/rpl-dag-root.c +++ b/os/net/routing/rpl-lite/rpl-dag-root.c @@ -40,7 +40,7 @@ #include "contiki.h" #include "contiki-net.h" -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" #include "net/ipv6/uip-ds6-route.h" /* Log configuration */ @@ -48,48 +48,6 @@ #define LOG_MODULE "RPL" #define LOG_LEVEL LOG_LEVEL_RPL -#define RPL_DAG_GRACE_PERIOD (CLOCK_SECOND * 20 * 1) - -static uint8_t to_become_root; -static struct ctimer c; - -/*---------------------------------------------------------------------------*/ -static void -create_dag_callback(void *ptr) -{ - const uip_ipaddr_t *root, *ipaddr; - - root = curr_instance.used ? &curr_instance.dag.dag_id : NULL; - ipaddr = rpl_get_global_address(); - - if(root == NULL || uip_ipaddr_cmp(root, ipaddr)) { - /* The RPL network we are joining is one that we created, so we - become root. */ - if(to_become_root) { - rpl_dag_root_init_dag_immediately(); - to_become_root = 0; - } - } else { - LOG_WARN("found a network we did not create: version %d grounded %d preference %d rank %d\n", - curr_instance.dag.version, curr_instance.dag.grounded, - curr_instance.dag.preference, curr_instance.dag.rank); - - /* We found a RPL network that we did not create so we just join - it without becoming root. But if the network has an infinite - rank, we assume the network has broken, and we become the new - root of the network. */ - - if(curr_instance.dag.rank == RPL_INFINITE_RANK) { - if(to_become_root) { - rpl_dag_root_init_dag_immediately(); - to_become_root = 0; - } - } - - /* Try again after the grace period */ - ctimer_set(&c, RPL_DAG_GRACE_PERIOD, create_dag_callback, NULL); - } -} /*---------------------------------------------------------------------------*/ static void set_global_address(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) @@ -125,26 +83,25 @@ set_global_address(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) } /*---------------------------------------------------------------------------*/ void -rpl_dag_root_init(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) +rpl_dag_root_set_prefix(uip_ipaddr_t *prefix, uip_ipaddr_t *iid) { static uint8_t initialized = 0; if(!initialized) { - to_become_root = 0; set_global_address(prefix, iid); initialized = 1; } } /*---------------------------------------------------------------------------*/ int -rpl_dag_root_init_dag_immediately(void) +rpl_dag_root_start(void) { struct uip_ds6_addr *root_if; int i; uint8_t state; uip_ipaddr_t *ipaddr = NULL; - rpl_dag_root_init(NULL, NULL); + rpl_dag_root_set_prefix(NULL, NULL); for(i = 0; i < UIP_DS6_ADDR_NB; i++) { state = uip_ds6_if.addr_list[i].state; @@ -170,18 +127,6 @@ rpl_dag_root_init_dag_immediately(void) } } /*---------------------------------------------------------------------------*/ -void -rpl_dag_root_init_dag_delay(void) -{ - rpl_dag_root_init(NULL, NULL); - - ctimer_set(&c, RPL_DAG_GRACE_PERIOD, create_dag_callback, NULL); - to_become_root = 1; - - /* Send a DIS packet to request RPL info from neighbors. */ - rpl_icmp6_dis_output(NULL); -} -/*---------------------------------------------------------------------------*/ int rpl_dag_root_is_root(void) { diff --git a/os/net/rpl-lite/rpl-dag-root.h b/os/net/routing/rpl-lite/rpl-dag-root.h similarity index 83% rename from os/net/rpl-lite/rpl-dag-root.h rename to os/net/routing/rpl-lite/rpl-dag-root.h index d6260ff219c49099272986d61a51ae6b392b426d..af0048c4d7273210330ebac0db7a178f604fb8b9 100644 --- a/os/net/rpl-lite/rpl-dag-root.h +++ b/os/net/routing/rpl-lite/rpl-dag-root.h @@ -43,26 +43,19 @@ /********** Public functions **********/ /** - * Initialize dag-root module and sets a prefix in case the node is later - * set as dag root. + * Set a prefix in case the node is later set as dag root. * * \param prefix The prefix. If NULL, UIP_DS6_DEFAULT_PREFIX is used instead * \param iid The IID. If NULL, it will be built from uip_ds6_set_addr_iid. */ -void rpl_dag_root_init(uip_ipaddr_t *prefix, uip_ipaddr_t *iid); +void rpl_dag_root_set_prefix(uip_ipaddr_t *prefix, uip_ipaddr_t *iid); /** - * Initializes the node as DAG root after a delay. Until the delay, the node - * gets a chance to hear another DAG and join it instead. -*/ -void rpl_dag_root_init_dag_delay(void); - -/** - * Initializes the node as DAG root immediatly. + * Set the node as root and start a DAG * * \return 0 in case of success, -1 otherwise */ -int rpl_dag_root_init_dag_immediately(void); +int rpl_dag_root_start(void); /** * Tells whether we are DAG root or not diff --git a/os/net/rpl-lite/rpl-dag.c b/os/net/routing/rpl-lite/rpl-dag.c similarity index 90% rename from os/net/rpl-lite/rpl-dag.c rename to os/net/routing/rpl-lite/rpl-dag.c index 36373dfb19438a5c3cac14ef8f073d2e23538bac..68d9e7aaac7723aceda0af487fcc1bf30b3046f3 100644 --- a/os/net/rpl-lite/rpl-dag.c +++ b/os/net/routing/rpl-lite/rpl-dag.c @@ -42,7 +42,8 @@ * Contributors: George Oikonomou <oikonomou@users.sourceforge.net> (multicast) */ -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" +#include "net/ipv6/uip-sr.h" #include "net/nbr-table.h" #include "net/link-stats.h" @@ -78,6 +79,16 @@ rpl_dag_state_to_str(enum rpl_dag_state state) } } /*---------------------------------------------------------------------------*/ +int +rpl_dag_get_root_ipaddr(uip_ipaddr_t *ipaddr) +{ + if(curr_instance.used && ipaddr != NULL) { + uip_ipaddr_copy(ipaddr, &curr_instance.dag.dag_id); + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ void rpl_dag_leave(void) { @@ -96,7 +107,7 @@ rpl_dag_leave(void) /* Remove all neighbors and lnks */ rpl_neighbor_remove_all(); - rpl_ns_free_all(); + uip_sr_free_all(); /* Stop all timers */ rpl_timers_stop_dag_timers(); @@ -169,18 +180,34 @@ find_objective_function(rpl_ocp_t ocp) } /*---------------------------------------------------------------------------*/ void -rpl_global_repair(void) +rpl_refresh_routes(const char *str) { if(rpl_dag_root_is_root()) { - LOG_WARN("initiating global repair, version %u, rank %u)\n", - curr_instance.dag.version, curr_instance.dag.rank); -#if LOG_INFO_ENABLED - rpl_neighbor_print_list("Global repair (before)"); -#endif /* LOG_INFO_ENABLED */ + /* Increment DTSN */ + RPL_LOLLIPOP_INCREMENT(curr_instance.dtsn_out); - /* Initiate global repair */ + LOG_WARN("incremented DTSN (%s), current %u\n", + str, curr_instance.dtsn_out); + if(LOG_INFO_ENABLED) { + rpl_neighbor_print_list("Refresh routes (before)"); + } + } +} +/*---------------------------------------------------------------------------*/ +void +rpl_global_repair(const char *str) +{ + if(rpl_dag_root_is_root()) { RPL_LOLLIPOP_INCREMENT(curr_instance.dag.version); /* New DAG version */ - RPL_LOLLIPOP_INCREMENT(curr_instance.dtsn_out); /* Request new DAOs */ + curr_instance.dtsn_out = RPL_LOLLIPOP_INIT; /* Re-initialize DTSN */ + + LOG_WARN("initiating global repair (%s), version %u, rank %u\n", + str, curr_instance.dag.version, curr_instance.dag.rank); + if(LOG_INFO_ENABLED) { + rpl_neighbor_print_list("Global repair (before)"); + } + + /* Now do a local repair to disseminate the new version */ rpl_local_repair("Global repair"); } } @@ -189,12 +216,13 @@ static void global_repair_non_root(rpl_dio_t *dio) { if(!rpl_dag_root_is_root()) { - LOG_WARN("participating in global repair, version %u, rank %u)\n", - curr_instance.dag.version, curr_instance.dag.rank); -#if LOG_INFO_ENABLED - rpl_neighbor_print_list("Global repair (before)"); -#endif /* LOG_INFO_ENABLED */ + LOG_WARN("participating in global repair, version %u, rank %u\n", + dio->version, curr_instance.dag.rank); + if(LOG_INFO_ENABLED) { + rpl_neighbor_print_list("Global repair (before)"); + } /* Re-initialize configuration from DIO */ + rpl_timers_stop_dag_timers(); init_dag_from_dio(dio); rpl_local_repair("Global repair"); } @@ -209,7 +237,6 @@ rpl_local_repair(const char *str) curr_instance.dag.state = DAG_INITIALIZED; /* Reset DAG state */ } curr_instance.of->reset(); /* Reset OF */ - link_stats_reset(); /* Forget past link statistics */ rpl_neighbor_remove_all(); /* Remove all neighbors */ rpl_timers_dio_reset("Local repair"); /* Reset Trickle timer */ rpl_timers_schedule_state_update(); @@ -314,9 +341,9 @@ rpl_dag_update_state(void) rpl_timers_schedule_leaving(); } -#if LOG_INFO_ENABLED - rpl_neighbor_print_list("Parent switch"); -#endif /* LOG_INFO_ENABLED */ + if(LOG_INFO_ENABLED) { + rpl_neighbor_print_list("Parent switch"); + } } } @@ -370,9 +397,15 @@ process_dio_from_current_dag(uip_ipaddr_t *from, rpl_dio_t *dio) return; } - /* If the DIO sender is on an older version of the DAG, ignore it. The node - will eventually hear the global repair and catch up. */ + /* If the DIO sender is on an older version of the DAG, do not process it + * further. The sender will eventually hear the global repair and catch up. */ if(rpl_lollipop_greater_than(curr_instance.dag.version, dio->version)) { + if(dio->rank == ROOT_RANK) { + /* Before returning, if the DIO was from the root, an old DAG versions + * likely incidates a root reboot. Reset our DIO timer to make sure the + * root hears our version ASAP, and in turn triggers a global repair. */ + rpl_timers_dio_reset("Heard old version from root"); + } return; } @@ -387,11 +420,13 @@ process_dio_from_current_dag(uip_ipaddr_t *from, rpl_dio_t *dio) * Must come first, as it might remove all neighbors, and we then need * to re-add this source of the DIO to the neighbor table */ if(rpl_lollipop_greater_than(dio->version, curr_instance.dag.version)) { - if(curr_instance.dag.rank == ROOT_RANK) { /* The root should not hear newer versions */ + if(curr_instance.dag.rank == ROOT_RANK) { + /* The root should not hear newer versions unless it just rebooted */ LOG_ERR("inconsistent DIO version (current: %u, received: %u), initiate global repair\n", curr_instance.dag.version, dio->version); - curr_instance.dag.version = dio->version; /* Update version and trigger global repair */ - rpl_global_repair(); + /* Update version and trigger global repair */ + curr_instance.dag.version = dio->version; + rpl_global_repair("Inconsistent DIO version"); } else { LOG_WARN("new DIO version (current: %u, received: %u), apply global repair\n", curr_instance.dag.version, dio->version); @@ -426,7 +461,7 @@ process_dio_from_current_dag(uip_ipaddr_t *from, rpl_dio_t *dio) if(curr_instance.mop != RPL_MOP_NO_DOWNWARD_ROUTES) { if(nbr != NULL && nbr == curr_instance.dag.preferred_parent && rpl_lollipop_greater_than(dio->dtsn, last_dtsn)) { RPL_LOLLIPOP_INCREMENT(curr_instance.dtsn_out); - LOG_INFO("DTSN increment %u->%u, schedule new DAO with DTSN %u", + LOG_WARN("DTSN increment %u->%u, schedule new DAO with DTSN %u\n", last_dtsn, dio->dtsn, curr_instance.dtsn_out); rpl_timers_schedule_dao(); } @@ -579,9 +614,9 @@ void rpl_process_dao(uip_ipaddr_t *from, rpl_dao_t *dao) { if(dao->lifetime == 0) { - rpl_ns_expire_parent(from, &dao->parent_addr); + uip_sr_expire_parent(NULL, from, &dao->parent_addr); } else { - if(!rpl_ns_update_node(from, &dao->parent_addr, RPL_LIFETIME(dao->lifetime))) { + if(!uip_sr_update_node(NULL, from, &dao->parent_addr, RPL_LIFETIME(dao->lifetime))) { LOG_ERR("failed to add link on incoming DAO\n"); return; } @@ -705,7 +740,6 @@ void rpl_dag_init(void) { memset(&curr_instance, 0, sizeof(curr_instance)); - rpl_neighbor_init(); } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/net/rpl-lite/rpl-dag.h b/os/net/routing/rpl-lite/rpl-dag.h similarity index 93% rename from os/net/rpl-lite/rpl-dag.h rename to os/net/routing/rpl-lite/rpl-dag.h index c3e22ae54fed1c9adb96dbd8509422d5ee43cc65..f9ae66f5fda60be4924cae2e6d3c5d4a78dc6e75 100644 --- a/os/net/rpl-lite/rpl-dag.h +++ b/os/net/routing/rpl-lite/rpl-dag.h @@ -28,6 +28,9 @@ * * This file is part of the Contiki operating system. * + */ + +/** * \addtogroup rpl-lite * @{ * @@ -55,6 +58,13 @@ * \return The description string */ const char *rpl_dag_state_to_str(enum rpl_dag_state state); +/** + * Returns the IPv6 address of the RPL DAG root, if any + * + * \param ipaddr A pointer where to copy the IP address of the DAG root + * \return 1 if the root address was copied, 0 otherwise +*/ +int rpl_dag_get_root_ipaddr(uip_ipaddr_t *ipaddr); /** * Start poisoning and leave the DAG after a delay * @@ -75,8 +85,10 @@ void rpl_dag_periodic(unsigned seconds); /** * Triggers a RPL global repair + * + * \param str A textual description of the cause for triggering a repair */ -void rpl_global_repair(void); +void rpl_global_repair(const char *str); /** * Triggers a RPL local repair diff --git a/os/net/rpl-lite/rpl-ext-header.c b/os/net/routing/rpl-lite/rpl-ext-header.c similarity index 91% rename from os/net/rpl-lite/rpl-ext-header.c rename to os/net/routing/rpl-lite/rpl-ext-header.c index e71e6c1f6f6e2906d5e3984a1996c194a76b5e91..af67cdaff88568bebf661b1c371925b708dabe7a 100644 --- a/os/net/rpl-lite/rpl-ext-header.c +++ b/os/net/routing/rpl-lite/rpl-ext-header.c @@ -42,8 +42,10 @@ * Nicolas Tsiftes <nvt@sics.se>, * Simon Duquennoy <simon.duquennoy@inria.fr> */ - -#include "net/rpl-lite/rpl.h" + +#include "net/routing/routing.h" +#include "net/routing/rpl-lite/rpl.h" +#include "net/ipv6/uip-sr.h" #include "net/packetbuf.h" /* Log configuration */ @@ -68,8 +70,8 @@ rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr) { uint8_t *uip_next_hdr; int last_uip_ext_len = uip_ext_len; - rpl_ns_node_t *dest_node; - rpl_ns_node_t *root_node; + uip_sr_node_t *dest_node; + uip_sr_node_t *root_node; uip_ext_len = 0; uip_next_hdr = &UIP_IP_BUF->proto; @@ -96,8 +98,8 @@ rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr) return 0; } - root_node = rpl_ns_get_node(&curr_instance.dag.dag_id); - dest_node = rpl_ns_get_node(&UIP_IP_BUF->destipaddr); + root_node = uip_sr_get_node(NULL, &curr_instance.dag.dag_id); + dest_node = uip_sr_get_node(NULL, &UIP_IP_BUF->destipaddr); if((uip_next_hdr != NULL && *uip_next_hdr == UIP_PROTO_ROUTING && UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) || @@ -227,9 +229,9 @@ insert_srh_header(void) uint8_t cmpri, cmpre; /* ComprI and ComprE fields of the RPL Source Routing Header */ uint8_t *hop_ptr; uint8_t padding; - rpl_ns_node_t *dest_node; - rpl_ns_node_t *root_node; - rpl_ns_node_t *node; + uip_sr_node_t *dest_node; + uip_sr_node_t *root_node; + uip_sr_node_t *node; uip_ipaddr_t node_addr; LOG_INFO("SRH creating source routing header with destination "); @@ -246,20 +248,20 @@ insert_srh_header(void) return 1; } - dest_node = rpl_ns_get_node(&UIP_IP_BUF->destipaddr); + dest_node = uip_sr_get_node(NULL, &UIP_IP_BUF->destipaddr); if(dest_node == NULL) { /* The destination is not found, skip SRH insertion */ LOG_INFO("SRH node not found, skip SRH insertion\n"); return 1; } - root_node = rpl_ns_get_node(&curr_instance.dag.dag_id); + root_node = uip_sr_get_node(NULL, &curr_instance.dag.dag_id); if(root_node == NULL) { LOG_ERR("SRH root node not found\n"); return 0; } - if(!rpl_ns_is_addr_reachable(&UIP_IP_BUF->destipaddr)) { + if(!uip_sr_is_addr_reachable(NULL, &UIP_IP_BUF->destipaddr)) { LOG_ERR("SRH no path found to destination\n"); return 0; } @@ -277,7 +279,7 @@ insert_srh_header(void) while(node != NULL && node != root_node) { - rpl_ns_get_node_global_addr(&node_addr, node); + NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node); /* How many bytes in common between all nodes in the path? */ cmpri = MIN(cmpri, count_matching_bytes(&node_addr, &UIP_IP_BUF->destipaddr, 16)); @@ -302,7 +304,7 @@ insert_srh_header(void) path_len, cmpri, cmpre, ext_len, padding); /* Check if there is enough space to store the extension header */ - if(uip_len + ext_len > UIP_BUFSIZE) { + if(uip_len + ext_len > UIP_BUFSIZE - UIP_LLH_LEN) { LOG_ERR("packet too long: impossible to add source routing header (%u bytes)\n", ext_len); return 0; } @@ -331,7 +333,7 @@ insert_srh_header(void) hop_ptr = ((uint8_t *)UIP_RH_BUF) + ext_len - padding; /* Pointer where to write the next hop compressed address */ while(node != NULL && node->parent != root_node) { - rpl_ns_get_node_global_addr(&node_addr, node); + NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node); hop_ptr -= (16 - cmpri); memcpy(hop_ptr, ((uint8_t*)&node_addr) + cmpri, 16 - cmpri); @@ -340,7 +342,7 @@ insert_srh_header(void) } /* The next hop (i.e. node whose parent is the root) is placed as the current IPv6 destination */ - rpl_ns_get_node_global_addr(&node_addr, node); + NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node); uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &node_addr); /* In-place update of IPv6 length field */ @@ -464,7 +466,7 @@ insert_hbh_header(void) /* Insert hop-by-hop header */ LOG_INFO("creating hop-by-hop option\n"); - if(uip_len + RPL_HOP_BY_HOP_LEN > UIP_BUFSIZE) { + if(uip_len + RPL_HOP_BY_HOP_LEN > UIP_BUFSIZE - UIP_LLH_LEN) { LOG_ERR("packet too long: impossible to add hop-by-hop option\n"); uip_ext_len = last_uip_ext_len; return 0; @@ -531,9 +533,11 @@ rpl_ext_header_remove(void) { uint8_t temp_len; uint8_t rpl_ext_hdr_len; + int uip_ext_opt_offset; uint8_t *uip_next_hdr; uip_ext_len = 0; + uip_ext_opt_offset = 2; uip_next_hdr = &UIP_IP_BUF->proto; /* Look for hop-by-hop and routing headers */ @@ -541,17 +545,22 @@ rpl_ext_header_remove(void) switch(*uip_next_hdr) { case UIP_PROTO_HBHO: case UIP_PROTO_ROUTING: - /* Remove hop-by-hop and routing headers */ - *uip_next_hdr = UIP_EXT_BUF->next; - rpl_ext_hdr_len = (UIP_EXT_BUF->len * 8) + 8; - temp_len = UIP_IP_BUF->len[1]; - uip_len -= rpl_ext_hdr_len; - UIP_IP_BUF->len[1] -= rpl_ext_hdr_len; - if(UIP_IP_BUF->len[1] > temp_len) { - UIP_IP_BUF->len[0]--; + if((*uip_next_hdr != UIP_PROTO_HBHO || UIP_EXT_HDR_OPT_RPL_BUF->opt_type == UIP_EXT_HDR_OPT_RPL)) { + /* Remove hop-by-hop and routing headers */ + *uip_next_hdr = UIP_EXT_BUF->next; + rpl_ext_hdr_len = (UIP_EXT_BUF->len * 8) + 8; + temp_len = UIP_IP_BUF->len[1]; + uip_len -= rpl_ext_hdr_len; + UIP_IP_BUF->len[1] -= rpl_ext_hdr_len; + if(UIP_IP_BUF->len[1] > temp_len) { + UIP_IP_BUF->len[0]--; + } + LOG_INFO("removing RPL extension header (type %u, len %u)\n", *uip_next_hdr, rpl_ext_hdr_len); + memmove(UIP_EXT_BUF, ((uint8_t *)UIP_EXT_BUF) + rpl_ext_hdr_len, uip_len - UIP_IPH_LEN); + } else { + uip_next_hdr = &UIP_EXT_BUF->next; + uip_ext_len += (UIP_EXT_BUF->len << 3) + 8; } - LOG_INFO("removing RPL extension header (type %u, len %u)\n", *uip_next_hdr, rpl_ext_hdr_len); - memmove(UIP_EXT_BUF, ((uint8_t *)UIP_EXT_BUF) + rpl_ext_hdr_len, uip_len - UIP_IPH_LEN); break; case UIP_PROTO_DESTO: /* @@ -565,6 +574,7 @@ rpl_ext_header_remove(void) /* Move to next header */ uip_next_hdr = &UIP_EXT_BUF->next; uip_ext_len += (UIP_EXT_BUF->len << 3) + 8; + break; default: return; } diff --git a/os/net/rpl-lite/rpl-ext-header.h b/os/net/routing/rpl-lite/rpl-ext-header.h similarity index 71% rename from os/net/rpl-lite/rpl-ext-header.h rename to os/net/routing/rpl-lite/rpl-ext-header.h index 3e339e6e2f3d80ad0662bcdab9fd5375c058248f..df61bc325f1a9f1a263cd76a65bbd2e13bae6849 100644 --- a/os/net/rpl-lite/rpl-ext-header.h +++ b/os/net/routing/rpl-lite/rpl-ext-header.h @@ -44,33 +44,34 @@ /********** Public functions **********/ - /** - * Look for next hop from SRH of current uIP packet. - * - * \param ipaddr A pointer to the address where to store the next hop. - * \return 1 if a next hop was found, 0 otherwise - */ - int rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr); +/** +* Look for next hop from SRH of current uIP packet. +* +* \param ipaddr A pointer to the address where to store the next hop. +* \return 1 if a next hop was found, 0 otherwise +*/ +int rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr); - /** - * Process and update SRH in-place, - * i.e. internal address swapping as per RFC6554 - * \return 1 if SRH found, 0 otherwise - */ - int rpl_ext_header_srh_update(void); +/** +* Process and update SRH in-place, +* i.e. internal address swapping as per RFC6554 +* \return 1 if SRH found, 0 otherwise +*/ +int rpl_ext_header_srh_update(void); - /** - * Process and update the RPL extension headers of the current uIP packet. - * - * \param uip_ext_opt_offset The offset within the uIP packet where - * extension headers start - * \return 1 in case the packet is valid and to be processed further, - * 0 in case the packet must be dropped. - */ - int rpl_ext_header_hbh_update(int uip_ext_opt_offset); +/** +* Process and update the RPL hop-by-hop extension headers of +* the current uIP packet. +* +* \param uip_ext_opt_offset The offset within the uIP packet where +* extension headers start +* \return 1 in case the packet is valid and to be processed further, +* 0 in case the packet must be dropped. +*/ +int rpl_ext_header_hbh_update(int uip_ext_opt_offset); /** - * Adds/updates RPL extension headers to current uIP packet. + * Adds/updates all RPL extension headers to current uIP packet. * * \return 1 in case of success, 0 otherwise */ diff --git a/os/net/rpl-lite/rpl-icmp6.c b/os/net/routing/rpl-lite/rpl-icmp6.c similarity index 99% rename from os/net/rpl-lite/rpl-icmp6.c rename to os/net/routing/rpl-lite/rpl-icmp6.c index 65c486be5be59489a96674129295bd9043243878..1e4a50423d03782f2385b86524e0d3f38ab041ba 100644 --- a/os/net/rpl-lite/rpl-icmp6.c +++ b/os/net/routing/rpl-lite/rpl-icmp6.c @@ -44,7 +44,7 @@ * George Oikonomou <oikonomou@users.sourceforge.net> (multicast) */ -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" #include "net/ipv6/uip-icmp6.h" #include "net/packetbuf.h" #include "lib/random.h" diff --git a/os/net/rpl-lite/rpl-icmp6.h b/os/net/routing/rpl-lite/rpl-icmp6.h similarity index 99% rename from os/net/rpl-lite/rpl-icmp6.h rename to os/net/routing/rpl-lite/rpl-icmp6.h index 443d28ef60927354b8739e3f32e622349203f327..fc877b948f7072c8f66ef39f463e93cf8d836f31 100644 --- a/os/net/rpl-lite/rpl-icmp6.h +++ b/os/net/routing/rpl-lite/rpl-icmp6.h @@ -44,6 +44,7 @@ #include "uip.h" #include "uip-ds6.h" +#include "uip-ds6-nbr.h" /********** Data structures **********/ diff --git a/os/net/rpl-lite/rpl-mrhof.c b/os/net/routing/rpl-lite/rpl-mrhof.c similarity index 93% rename from os/net/rpl-lite/rpl-mrhof.c rename to os/net/routing/rpl-lite/rpl-mrhof.c index 9f9ba288992fa34bf0d7811912273dc0b5fecc9e..5504f4fda4781f822f16f058fc8343a8d5e5acb2 100644 --- a/os/net/rpl-lite/rpl-mrhof.c +++ b/os/net/routing/rpl-lite/rpl-mrhof.c @@ -45,7 +45,7 @@ * Simon Duquennoy <simon.duquennoy@inria.fr> */ -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" #include "net/nbr-table.h" #include "net/link-stats.h" @@ -56,18 +56,23 @@ /* RFC6551 and RFC6719 do not mandate the use of a specific formula to * compute the ETX value. This MRHOF implementation relies on the value - * computed by the link-stats module. It has an optional feature, + * computed by the link-stats module.It has an optional feature, * RPL_MRHOF_CONF_SQUARED_ETX, that consists in squaring this value. - * This basically penalizes bad links while preserving the semantics of ETX + * + * Squaring basically penalizes bad links while preserving the semantics of ETX * (1 = perfect link, more = worse link). As a result, MRHOF will favor - * good links over short paths. Recommended when reliability is a priority. - * Without this feature, a hop with 50% PRR (ETX=2) is equivalent to two - * perfect hops with 100% PRR (ETX=1+1=2). With this feature, the former - * path obtains ETX=2*2=4 and the former ETX=1*1+1*1=2. */ + * good links over short paths. Without this feature, a hop with 50% PRR (ETX=2) + * is equivalent to two perfect hops with 100% PRR (ETX=1+1=2). With this + * feature, the former path obtains ETX=2*2=4 and the former ETX=1*1+1*1=2. + * + * While this feature helps achieve extra relaibility, it also results in + * added churn. In networks with high congestion or poor links, this can lead + * to poor connectivity due to more parent switches, loops, Trickle resets, etc. + */ #ifdef RPL_MRHOF_CONF_SQUARED_ETX #define RPL_MRHOF_SQUARED_ETX RPL_MRHOF_CONF_SQUARED_ETX #else /* RPL_MRHOF_CONF_SQUARED_ETX */ -#define RPL_MRHOF_SQUARED_ETX 1 +#define RPL_MRHOF_SQUARED_ETX 0 #endif /* RPL_MRHOF_CONF_SQUARED_ETX */ /* Configuration parameters of RFC6719. Reject parents that have a higher diff --git a/os/net/rpl-lite/rpl-nbr-policy.c b/os/net/routing/rpl-lite/rpl-nbr-policy.c similarity index 90% rename from os/net/rpl-lite/rpl-nbr-policy.c rename to os/net/routing/rpl-lite/rpl-nbr-policy.c index 0a8da44d4c5ce59fe8f4fb3776aa29d5d20a5172..3db84f3a8928f33a7b5b9e8fadb3fcbebcdf9e5c 100644 --- a/os/net/rpl-lite/rpl-nbr-policy.c +++ b/os/net/routing/rpl-lite/rpl-nbr-policy.c @@ -42,7 +42,7 @@ * */ -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" #include "net/nbr-table.h" /* Log configuration */ @@ -65,19 +65,7 @@ static int num_parents; /* all nodes that are possible parents */ static int num_free; static linkaddr_t *worst_rank_nbr_lladdr; /* lladdr of the the neighbor with the worst rank */ static rpl_rank_t worst_rank; -/*---------------------------------------------------------------------------*/ -#if LOG_DBG_ENABLED -/* Print out state periodically */ -static void update_state(void); -static struct ctimer periodic_timer; -static int timer_init = 0; -static void -handle_periodic_timer(void *ptr) -{ - update_state(); - ctimer_restart(&periodic_timer); -} -#endif /* LOG_DBG_ENABLED */ + /*---------------------------------------------------------------------------*/ static void update_state(void) @@ -87,14 +75,6 @@ update_state(void) rpl_rank_t nbr_rank; int num_used = 0; -#if LOG_DBG_ENABLED - if(!timer_init) { - timer_init = 1; - ctimer_set(&periodic_timer, 60 * CLOCK_SECOND, - &handle_periodic_timer, NULL); - } -#endif /* LOG_DBG_ENABLED */ - worst_rank = 0; worst_rank_nbr_lladdr = NULL; num_parents = 0; diff --git a/os/net/rpl-lite/rpl-neighbor.c b/os/net/routing/rpl-lite/rpl-neighbor.c similarity index 96% rename from os/net/rpl-lite/rpl-neighbor.c rename to os/net/routing/rpl-lite/rpl-neighbor.c index 96c85a886b67b2c32da427c93d4da61de48d9527..8afa2440fc11b939cb77a86fb20a76fad00209aa 100644 --- a/os/net/rpl-lite/rpl-neighbor.c +++ b/os/net/routing/rpl-lite/rpl-neighbor.c @@ -43,7 +43,7 @@ */ #include "contiki.h" -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" #include "net/link-stats.h" #include "net/nbr-table.h" @@ -63,6 +63,18 @@ static rpl_nbr_t * best_parent(int fresh_only); /* Per-neighbor RPL information */ NBR_TABLE_GLOBAL(rpl_nbr_t, rpl_neighbors); +/*---------------------------------------------------------------------------*/ +static int +max_acceptable_rank(void) +{ + if(curr_instance.max_rankinc == 0) { + /* There is no max rank increment */ + return RPL_INFINITE_RANK; + } else { + /* Make sure not to exceed RPL_INFINITE_RANK */ + return MIN((uint32_t)curr_instance.dag.lowest_rank + curr_instance.max_rankinc, RPL_INFINITE_RANK); + } +} /*---------------------------------------------------------------------------*/ /* As per RFC 6550, section 8.2.2.4 */ static int @@ -70,8 +82,7 @@ acceptable_rank(rpl_rank_t rank) { return rank != RPL_INFINITE_RANK && rank >= ROOT_RANK - && ((curr_instance.max_rankinc == 0) || - rank <= curr_instance.dag.lowest_rank + curr_instance.max_rankinc); + && rank <= max_acceptable_rank(); } /*---------------------------------------------------------------------------*/ void @@ -89,7 +100,7 @@ rpl_neighbor_print_list(const char *str) LOG_INFO_(", DAG state: %s, MOP %u OCP %u rank %u max-rank %u, dioint %u, nbr count %u (%s)\n", rpl_dag_state_to_str(curr_instance.dag.state), curr_instance.mop, curr_instance.of->ocp, curr_rank, - curr_instance.max_rankinc != 0 ? curr_instance.dag.lowest_rank + curr_instance.max_rankinc : 0xffff, + max_acceptable_rank(), curr_dio_interval, rpl_neighbor_count(), str); while(nbr != NULL) { const struct link_stats *stats = rpl_neighbor_get_link_stats(nbr); diff --git a/os/net/rpl-lite/rpl-neighbor.h b/os/net/routing/rpl-lite/rpl-neighbor.h similarity index 99% rename from os/net/rpl-lite/rpl-neighbor.h rename to os/net/routing/rpl-lite/rpl-neighbor.h index e81c5bcc6263221f70455d9d77a61d482a63d828..028d089c73f7f8ec8cf4845169ecbc33b4f2c124 100644 --- a/os/net/rpl-lite/rpl-neighbor.h +++ b/os/net/routing/rpl-lite/rpl-neighbor.h @@ -28,6 +28,9 @@ * * This file is part of the Contiki operating system. * + */ + + /** * \addtogroup rpl-lite * @{ * @@ -44,7 +47,7 @@ /********** Includes **********/ -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" #include "lib/list.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" diff --git a/os/net/rpl-lite/rpl-of0.c b/os/net/routing/rpl-lite/rpl-of0.c similarity index 99% rename from os/net/rpl-lite/rpl-of0.c rename to os/net/routing/rpl-lite/rpl-of0.c index 0e94f73f90a9e623f53e36cc4e134a88abe9eaf5..c6f820157bf010dd3f85642548df9f5ca87be9c2 100644 --- a/os/net/rpl-lite/rpl-of0.c +++ b/os/net/routing/rpl-lite/rpl-of0.c @@ -41,7 +41,7 @@ * Simon Duquennoy <simon.duquennoy@inria.fr> */ -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" #include "net/nbr-table.h" #include "net/link-stats.h" diff --git a/os/net/rpl-lite/rpl-timers.c b/os/net/routing/rpl-lite/rpl-timers.c similarity index 97% rename from os/net/rpl-lite/rpl-timers.c rename to os/net/routing/rpl-lite/rpl-timers.c index 486ccd5b40dd508b81da932f2b0871f6ba7664b7..6cd188f9d1e2dfc0118ed84af40ad2c30bdcdae0 100644 --- a/os/net/rpl-lite/rpl-timers.c +++ b/os/net/routing/rpl-lite/rpl-timers.c @@ -41,7 +41,8 @@ */ #include "contiki.h" -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" +#include "net/ipv6/uip-sr.h" #include "net/link-stats.h" #include "lib/random.h" #include "sys/ctimer.h" @@ -256,8 +257,8 @@ void rpl_timers_schedule_dao(void) { if(curr_instance.used && curr_instance.mop != RPL_MOP_NO_DOWNWARD_ROUTES) { - /* No need for aggregation delay as per RFC 6550 section 9.5, as this only - * serves storing mode. Use simply delay instead, with the only PURPOSE + /* No need for DAO aggregation delay as per RFC 6550 section 9.5, as this + * only serves storing mode. Use simple delay instead, with the only purpose * to reduce congestion. */ clock_time_t expiration_time = RPL_DAO_DELAY / 2 + (random_rand() % (RPL_DAO_DELAY)); /* Increment next seqno */ @@ -305,8 +306,10 @@ handle_dao_timer(void *ptr) rpl_icmp6_dao_output(curr_instance.default_lifetime); #if !RPL_WITH_DAO_ACK - /* There is DAO-ACK, schedule a refresh. Must be done after rpl_icmp6_dao_output, - because we increment curr_instance.dag.dao_curr_seqno for the next DAO (refresh) */ + /* There is no DAO-ACK, schedule a refresh. Must be done after rpl_icmp6_dao_output, + because we increment curr_instance.dag.dao_curr_seqno for the next DAO (refresh). + Where there is DAO-ACK, the refresh is scheduled after reception of the ACK. + Happens when handle_dao_timer is called again next. */ schedule_dao_refresh(); #endif /* !RPL_WITH_DAO_ACK */ } @@ -432,7 +435,7 @@ handle_probing_timer(void *ptr) LOG_INFO_6ADDR(target_ipaddr); LOG_INFO_(" %s last tx %u min ago\n", curr_instance.dag.urgent_probing_target != NULL ? "(urgent)" : "", - probing_target != NULL ? + stats != NULL ? (unsigned)((clock_time() - stats->last_tx_time) / (60 * CLOCK_SECOND)) : 0 ); /* Send probe, e.g. unicast DIO or DIS */ @@ -500,7 +503,7 @@ handle_periodic_timer(void *ptr) { if(curr_instance.used) { rpl_dag_periodic(PERIODIC_DELAY_SECONDS); - rpl_ns_periodic(PERIODIC_DELAY_SECONDS); + uip_sr_periodic(PERIODIC_DELAY_SECONDS); } if(!curr_instance.used || @@ -513,9 +516,9 @@ handle_periodic_timer(void *ptr) the meaning of last_advertised_rank changes with time */ rpl_dag_update_state(); -#if LOG_INFO_ENABLED - rpl_neighbor_print_list("Periodic"); -#endif /* LOG_INFO_ENABLED */ + if(LOG_INFO_ENABLED) { + rpl_neighbor_print_list("Periodic"); + } ctimer_reset(&periodic_timer); } diff --git a/os/net/rpl-lite/rpl-timers.h b/os/net/routing/rpl-lite/rpl-timers.h similarity index 98% rename from os/net/rpl-lite/rpl-timers.h rename to os/net/routing/rpl-lite/rpl-timers.h index a37d5df36167a6b2311b3233364eb5a230a2c236..884a55696b47dc33a9a809d55053bb5f8fde511f 100644 --- a/os/net/rpl-lite/rpl-timers.h +++ b/os/net/routing/rpl-lite/rpl-timers.h @@ -28,6 +28,9 @@ * * This file is part of the Contiki operating system. * + */ + + /** * \addtogroup rpl-lite * @{ * @@ -44,7 +47,7 @@ /********** Includes **********/ -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" /********** Public functions **********/ diff --git a/os/net/rpl-lite/rpl-types.h b/os/net/routing/rpl-lite/rpl-types.h similarity index 86% rename from os/net/rpl-lite/rpl-types.h rename to os/net/routing/rpl-lite/rpl-types.h index 53856f66d878beb037154bd9e321a632cf86bdbe..16dfa057e6c1350446ab3b0d778efc5807dae1da 100644 --- a/os/net/rpl-lite/rpl-types.h +++ b/os/net/routing/rpl-lite/rpl-types.h @@ -28,6 +28,9 @@ * * This file is part of the Contiki operating system. * + */ + + /** * \addtogroup rpl-lite * @{ * @@ -65,19 +68,18 @@ ((addr)->u8[14] == 0) && \ ((addr)->u8[15] == 0x1a)) -/* Compute lifetime, accounting for the lifetime unit */ +/** \brief Compute lifetime, accounting for the lifetime unit */ #define RPL_LIFETIME(lifetime) \ (((lifetime) == RPL_INFINITE_LIFETIME) ? \ RPL_ROUTE_INFINITE_LIFETIME : \ (unsigned long)curr_instance.lifetime_unit * (lifetime)) -/* Rank of a root node. */ +/** \brief Rank of a root node. */ #define ROOT_RANK curr_instance.min_hoprankinc -/* Return DAG RANK as per RFC 6550 (rank divided by min_hoprankinc) */ +/** \brief Return DAG RANK as per RFC 6550 (rank divided by min_hoprankinc) */ #define DAG_RANK(fixpt_rank) ((fixpt_rank) / curr_instance.min_hoprankinc) -/* Lollipop counters */ #define RPL_LOLLIPOP_MAX_VALUE 255 #define RPL_LOLLIPOP_CIRCULAR_REGION 127 #define RPL_LOLLIPOP_SEQUENCE_WINDOWS 16 @@ -94,18 +96,20 @@ #define RPL_LOLLIPOP_IS_INIT(counter) \ ((counter) > RPL_LOLLIPOP_CIRCULAR_REGION) + /********** Data structures and types **********/ typedef uint16_t rpl_rank_t; typedef uint16_t rpl_ocp_t; /*---------------------------------------------------------------------------*/ +/** \brief Structure for RPL energy metric. */ struct rpl_metric_object_energy { uint8_t flags; uint8_t energy_est; }; -/* Logical representation of a DAG Metric Container. */ +/** \brief Logical representation of a DAG Metric Container. */ struct rpl_metric_container { uint8_t type; uint8_t flags; @@ -119,7 +123,7 @@ struct rpl_metric_container { }; typedef struct rpl_metric_container rpl_metric_container_t; -/* RPL prefix information */ +/** \brief RPL prefix information */ struct rpl_prefix { uip_ipaddr_t prefix; uint32_t lifetime; @@ -128,7 +132,7 @@ struct rpl_prefix { }; typedef struct rpl_prefix rpl_prefix_t; -/* All information related to a RPL neighbor */ +/** \brief All information related to a RPL neighbor */ struct rpl_nbr { clock_time_t better_parent_since; /* The neighbor has been a possible replacement for our preferred parent consistently since 'parent_since'. @@ -142,18 +146,18 @@ struct rpl_nbr { typedef struct rpl_nbr rpl_nbr_t; /*---------------------------------------------------------------------------*/ - /* - * API for RPL objective functions (OF) + /** + * \brief API for RPL objective functions (OF) * - * reset(dag) Resets the objective function state for a specific DAG. This function is + * - reset(dag) Resets the objective function state for a specific DAG. This function is * called when doing a global repair on the DAG. - * nbr_link_metric(n) Returns the link metric of a neighbor - * nbr_has_usable_link(n) Returns 1 iff the neighbor has a usable link as defined by the OF - * nbr_is_acceptable_parent(n) Returns 1 iff the neighbor has a usable rank/link as defined by the OF - * nbr_path_cost(n) Returns the path cost of a neighbor - * rank_via_nbr(n) Returns our rank if we select a given neighbor as preferred parent - * best_parent(n1, n2) Compares two neighbors and returns the best one, according to the OF. - * update_metric_container() Updated the DAG metric container from the current OF state + * - nbr_link_metric(n) Returns the link metric of a neighbor + * - nbr_has_usable_link(n) Returns 1 iff the neighbor has a usable link as defined by the OF + * - nbr_is_acceptable_parent(n) Returns 1 iff the neighbor has a usable rank/link as defined by the OF + * - nbr_path_cost(n) Returns the path cost of a neighbor + * - rank_via_nbr(n) Returns our rank if we select a given neighbor as preferred parent + * - best_parent(n1, n2) Compares two neighbors and returns the best one, according to the OF. + * - update_metric_container() Updated the DAG metric container from the current OF state */ struct rpl_of { void (*reset)(void); @@ -169,7 +173,7 @@ typedef struct rpl_nbr rpl_nbr_t; typedef struct rpl_of rpl_of_t; /*---------------------------------------------------------------------------*/ -/* Directed Acyclic Graph */ +/** \brief RPL DAG states*/ enum rpl_dag_state { DAG_INITIALIZED, DAG_JOINED, @@ -177,6 +181,7 @@ enum rpl_dag_state { DAG_POISONING }; +/** \brief RPL DAG structure */ struct rpl_dag { uip_ipaddr_t dag_id; rpl_prefix_t prefix_info; @@ -218,7 +223,7 @@ struct rpl_dag { typedef struct rpl_dag rpl_dag_t; /*---------------------------------------------------------------------------*/ -/* Instance */ +/** \brief RPL instance structure */ struct rpl_instance { rpl_metric_container_t mc; /* Metric container. Set to MC_NONE when no mc is used */ rpl_of_t *of; /* The objective function */ diff --git a/os/net/rpl-lite/rpl.c b/os/net/routing/rpl-lite/rpl.c similarity index 76% rename from os/net/rpl-lite/rpl.c rename to os/net/routing/rpl-lite/rpl.c index 76d49d5626c5736b79cd2c05eab88ac7e02656d9..acfe94c37b967bdcb09ddd4c435306d22437e3bc 100644 --- a/os/net/rpl-lite/rpl.c +++ b/os/net/routing/rpl-lite/rpl.c @@ -41,7 +41,8 @@ * Simon Duquennoy <simon.duquennoy@inria.fr> */ -#include "net/rpl-lite/rpl.h" +#include "net/routing/rpl-lite/rpl.h" +#include "net/routing/routing.h" /* Log configuration */ #include "sys/log.h" @@ -71,12 +72,20 @@ rpl_get_global_address(void) int i; uint8_t state; uip_ipaddr_t *ipaddr = NULL; + uip_ipaddr_t *prefix = NULL; + uint8_t prefix_length = 0; + + if(curr_instance.used && curr_instance.dag.prefix_info.length != 0) { + prefix = &curr_instance.dag.prefix_info.prefix; + prefix_length = curr_instance.dag.prefix_info.length; + } for(i = 0; i < UIP_DS6_ADDR_NB; i++) { state = uip_ds6_if.addr_list[i].state; if(uip_ds6_if.addr_list[i].isused && state == ADDR_PREFERRED && - !uip_is_addr_linklocal(&uip_ds6_if.addr_list[i].ipaddr)) { + !uip_is_addr_linklocal(&uip_ds6_if.addr_list[i].ipaddr) && + (prefix == NULL || uip_ipaddr_prefixcmp(prefix, &uip_ds6_if.addr_list[i].ipaddr, prefix_length))) { ipaddr = &uip_ds6_if.addr_list[i].ipaddr; } } @@ -100,6 +109,12 @@ rpl_link_callback(const linkaddr_t *addr, int status, int numtx) } /*---------------------------------------------------------------------------*/ int +rpl_has_joined(void) +{ + return curr_instance.used && curr_instance.dag.state >= DAG_JOINED; +} +/*---------------------------------------------------------------------------*/ +int rpl_is_reachable(void) { return curr_instance.used && curr_instance.dag.state == DAG_REACHABLE; @@ -167,8 +182,8 @@ rpl_set_prefix(rpl_prefix_t *prefix) return 0; } /*---------------------------------------------------------------------------*/ -void -rpl_init(void) +static void +init(void) { LOG_INFO("initializing\n"); @@ -181,8 +196,55 @@ rpl_init(void) rpl_timers_init(); rpl_icmp6_init(); - rpl_ns_init(); + uip_sr_init(); } /*---------------------------------------------------------------------------*/ +static int +get_sr_node_ipaddr(uip_ipaddr_t *addr, const uip_sr_node_t *node) +{ + if(addr != NULL && node != NULL) { + memcpy(addr, &curr_instance.dag.dag_id, 8); + memcpy(((unsigned char *)addr) + 8, &node->link_identifier, 8); + return 1; + } else { + return 0; + } +} +/*---------------------------------------------------------------------------*/ +static void +neighbor_state_changed(uip_ds6_nbr_t *nbr) +{ + /* Nothing needs be done in non-storing mode */ +} +/*---------------------------------------------------------------------------*/ +static void +drop_route(uip_ds6_route_t *route) +{ + /* Do nothing. RPL-lite only supports non-storing mode, i.e. no routes */ +} +/*---------------------------------------------------------------------------*/ +const struct routing_driver rpl_lite_driver = { + "RPL Lite", + init, + rpl_dag_root_set_prefix, + rpl_dag_root_start, + rpl_dag_root_is_root, + rpl_dag_get_root_ipaddr, + get_sr_node_ipaddr, + rpl_dag_poison_and_leave, + rpl_has_joined, + rpl_is_reachable, + rpl_global_repair, + rpl_local_repair, + rpl_ext_header_remove, + rpl_ext_header_update, + rpl_ext_header_hbh_update, + rpl_ext_header_srh_update, + rpl_ext_header_srh_get_next_hop, + rpl_link_callback, + neighbor_state_changed, + drop_route, +}; +/*---------------------------------------------------------------------------*/ /** @}*/ diff --git a/os/net/rpl-lite/rpl.h b/os/net/routing/rpl-lite/rpl.h similarity index 87% rename from os/net/rpl-lite/rpl.h rename to os/net/routing/rpl-lite/rpl.h index 9557f41c35d31ec513c877a3494f87b0ef68389a..25ac3863e8be3794a6befaa1ad5bf9442e80d30b 100644 --- a/os/net/rpl-lite/rpl.h +++ b/os/net/routing/rpl-lite/rpl.h @@ -48,16 +48,15 @@ /********** Includes **********/ #include "net/ipv6/uip.h" -#include "net/rpl-lite/rpl-const.h" -#include "net/rpl-lite/rpl-conf.h" -#include "net/rpl-lite/rpl-types.h" -#include "net/rpl-lite/rpl-icmp6.h" -#include "net/rpl-lite/rpl-dag.h" -#include "net/rpl-lite/rpl-ns.h" -#include "net/rpl-lite/rpl-dag-root.h" -#include "net/rpl-lite/rpl-neighbor.h" -#include "net/rpl-lite/rpl-ext-header.h" -#include "net/rpl-lite/rpl-timers.h" +#include "net/routing/rpl-lite/rpl-const.h" +#include "net/routing/rpl-lite/rpl-conf.h" +#include "net/routing/rpl-lite/rpl-types.h" +#include "net/routing/rpl-lite/rpl-icmp6.h" +#include "net/routing/rpl-lite/rpl-dag.h" +#include "net/routing/rpl-lite/rpl-dag-root.h" +#include "net/routing/rpl-lite/rpl-neighbor.h" +#include "net/routing/rpl-lite/rpl-ext-header.h" +#include "net/routing/rpl-lite/rpl-timers.h" /********** Public symbols **********/ @@ -128,9 +127,11 @@ int rpl_is_reachable(void); int rpl_lollipop_greater_than(int a, int b); /** - * Initialize RPL main module + * Triggers a route fresh via DTSN increment + * + * \param str a textual description of the cause for refresh */ -void rpl_init(void); +void rpl_refresh_routes(const char *str); /** @} */ diff --git a/os/net/rpl-classic/rpl-ns.c b/os/net/rpl-classic/rpl-ns.c deleted file mode 100644 index 523aab76cffde57e511bb676dc3a6e6fac1e2bc2..0000000000000000000000000000000000000000 --- a/os/net/rpl-classic/rpl-ns.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2016, Inria. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - */ - -/** - * \file - * RPL non-storing mode specific functions. Includes support for - * source routing. - * - * \author Simon Duquennoy <simon.duquennoy@inria.fr> - */ - -#include "net/rpl-classic/rpl-conf.h" - -#include "net/ipv6/uip.h" -#include "net/ipv6/tcpip.h" -#include "net/ipv6/uip-ds6.h" -#include "net/ipv6/uip-icmp6.h" -#include "net/rpl-classic/rpl-private.h" -#include "net/rpl-classic/rpl-ns.h" -#include "lib/list.h" -#include "lib/memb.h" - -#if RPL_WITH_NON_STORING - -#define DEBUG DEBUG_NONE -#include "net/ipv6/uip-debug.h" - -#include <limits.h> -#include <string.h> - -/* Total number of nodes */ -static int num_nodes; - -/* Every known node in the network */ -LIST(nodelist); -MEMB(nodememb, rpl_ns_node_t, RPL_NS_LINK_NUM); - -/*---------------------------------------------------------------------------*/ -int -rpl_ns_num_nodes(void) -{ - return num_nodes; -} -/*---------------------------------------------------------------------------*/ -static int -node_matches_address(const rpl_dag_t *dag, const rpl_ns_node_t *node, const uip_ipaddr_t *addr) -{ - return addr != NULL - && node != NULL - && dag != NULL - && dag == node->dag - && !memcmp(addr, &node->dag->dag_id, 8) - && !memcmp(((const unsigned char *)addr) + 8, node->link_identifier, 8); -} -/*---------------------------------------------------------------------------*/ -rpl_ns_node_t * -rpl_ns_get_node(const rpl_dag_t *dag, const uip_ipaddr_t *addr) -{ - rpl_ns_node_t *l; - for(l = list_head(nodelist); l != NULL; l = list_item_next(l)) { - /* Compare prefix and node identifier */ - if(node_matches_address(dag, l, addr)) { - return l; - } - } - return NULL; -} -/*---------------------------------------------------------------------------*/ -int -rpl_ns_is_node_reachable(const rpl_dag_t *dag, const uip_ipaddr_t *addr) -{ - int max_depth = RPL_NS_LINK_NUM; - rpl_ns_node_t *node = rpl_ns_get_node(dag, addr); - rpl_ns_node_t *root_node = rpl_ns_get_node(dag, dag != NULL ? &dag->dag_id : NULL); - while(node != NULL && node != root_node && max_depth > 0) { - node = node->parent; - max_depth--; - } - return node != NULL && node == root_node; -} -/*---------------------------------------------------------------------------*/ -void -rpl_ns_expire_parent(rpl_dag_t *dag, const uip_ipaddr_t *child, const uip_ipaddr_t *parent) -{ - rpl_ns_node_t *l = rpl_ns_get_node(dag, child); - /* Check if parent matches */ - if(l != NULL && node_matches_address(dag, l->parent, parent)) { - l->lifetime = RPL_NOPATH_REMOVAL_DELAY; - } -} -/*---------------------------------------------------------------------------*/ -rpl_ns_node_t * -rpl_ns_update_node(rpl_dag_t *dag, const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime) -{ - rpl_ns_node_t *child_node = rpl_ns_get_node(dag, child); - rpl_ns_node_t *parent_node = rpl_ns_get_node(dag, parent); - rpl_ns_node_t *old_parent_node; - - if(parent != NULL) { - /* No node for the parent, add one with infinite lifetime */ - if(parent_node == NULL) { - parent_node = rpl_ns_update_node(dag, parent, NULL, 0xffffffff); - if(parent_node == NULL) { - return NULL; - } - } - } - - /* No node for this child, add one */ - if(child_node == NULL) { - child_node = memb_alloc(&nodememb); - /* No space left, abort */ - if(child_node == NULL) { - return NULL; - } - child_node->parent = NULL; - list_add(nodelist, child_node); - num_nodes++; - } - - /* Initialize node */ - child_node->dag = dag; - child_node->lifetime = lifetime; - memcpy(child_node->link_identifier, ((const unsigned char *)child) + 8, 8); - - /* Is the node reachable before the update? */ - if(rpl_ns_is_node_reachable(dag, child)) { - old_parent_node = child_node->parent; - /* Update node */ - child_node->parent = parent_node; - /* Has the node become unreachable? May happen if we create a loop. */ - if(!rpl_ns_is_node_reachable(dag, child)) { - /* The new parent makes the node unreachable, restore old parent. - * We will take the update next time, with chances we know more of - * the topology and the loop is gone. */ - child_node->parent = old_parent_node; - } - } else { - child_node->parent = parent_node; - } - - return child_node; -} -/*---------------------------------------------------------------------------*/ -void -rpl_ns_init(void) -{ - num_nodes = 0; - memb_init(&nodememb); - list_init(nodelist); -} -/*---------------------------------------------------------------------------*/ -rpl_ns_node_t * -rpl_ns_node_head(void) -{ - return list_head(nodelist); -} -/*---------------------------------------------------------------------------*/ -rpl_ns_node_t * -rpl_ns_node_next(rpl_ns_node_t *item) -{ - return list_item_next(item); -} -/*---------------------------------------------------------------------------*/ -void -rpl_ns_get_node_global_addr(uip_ipaddr_t *addr, rpl_ns_node_t *node) -{ - if(addr != NULL && node != NULL && node->dag != NULL) { - memcpy(addr, &node->dag->dag_id, 8); - memcpy(((unsigned char *)addr) + 8, &node->link_identifier, 8); - } -} -/*---------------------------------------------------------------------------*/ -void -rpl_ns_periodic(void) -{ - rpl_ns_node_t *l; - /* First pass, decrement lifetime for all nodes with non-infinite lifetime */ - for(l = list_head(nodelist); l != NULL; l = list_item_next(l)) { - /* Don't touch infinite lifetime nodes */ - if(l->lifetime != 0xffffffff && l->lifetime > 0) { - l->lifetime--; - } - } - /* Second pass, for all expired nodes, deallocate them iff no child points to them */ - for(l = list_head(nodelist); l != NULL; l = list_item_next(l)) { - if(l->lifetime == 0) { - rpl_ns_node_t *l2; - for(l2 = list_head(nodelist); l2 != NULL; l2 = list_item_next(l2)) { - if(l2->parent == l) { - break; - } - } - /* No child found, deallocate node */ - list_remove(nodelist, l); - memb_free(&nodememb, l); - num_nodes--; - } - } -} - -#endif /* RPL_WITH_NON_STORING */ diff --git a/os/net/rpl-classic/rpl-ns.h b/os/net/rpl-classic/rpl-ns.h deleted file mode 100644 index f6ae4c2c6d33d08ef62bae5631b90c7eb4430fc8..0000000000000000000000000000000000000000 --- a/os/net/rpl-classic/rpl-ns.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2016, Inria. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - */ - -/** - * \file - * RPL non-storing mode specific functions. Includes support for - * source routing. - * - * \author Simon Duquennoy <simon.duquennoy@inria.fr> - */ - - -#ifndef RPL_NS_H -#define RPL_NS_H - -#include "net/rpl-classic/rpl-conf.h" - -#ifdef RPL_NS_CONF_LINK_NUM -#define RPL_NS_LINK_NUM RPL_NS_CONF_LINK_NUM -#else /* RPL_NS_CONF_LINK_NUM */ -#if RPL_WITH_NON_STORING -#define RPL_NS_LINK_NUM NETSTACK_MAX_ROUTE_ENTRIES -#else -#define RPL_NS_LINK_NUM 0 -#endif -#endif /* RPL_NS_CONF_LINK_NUM */ - -typedef struct rpl_ns_node { - struct rpl_ns_node *next; - uint32_t lifetime; - /* Store only IPv6 link identifiers as all nodes in the DAG share the same prefix */ - unsigned char link_identifier[8]; - struct rpl_ns_node *parent; -} rpl_ns_node_t; - -int rpl_ns_num_nodes(void); -void rpl_ns_expire_parent(rpl_dag_t *dag, const uip_ipaddr_t *child, const uip_ipaddr_t *parent); -rpl_ns_node_t *rpl_ns_update_node(rpl_dag_t *dag, const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime); -void rpl_ns_init(void); -rpl_ns_node_t *rpl_ns_node_head(void); -rpl_ns_node_t *rpl_ns_node_next(rpl_ns_node_t *item); -rpl_ns_node_t *rpl_ns_get_node(const rpl_dag_t *dag, const uip_ipaddr_t *addr); -int rpl_ns_is_node_reachable(const rpl_dag_t *dag, const uip_ipaddr_t *addr); -void rpl_ns_get_node_global_addr(uip_ipaddr_t *addr, rpl_ns_node_t *node); -void rpl_ns_periodic(void); - -#endif /* RPL_NS_H */ diff --git a/os/net/security/tinydtls b/os/net/security/tinydtls new file mode 160000 index 0000000000000000000000000000000000000000..5ec7ad12984eebf22a7eb5d779f24945db4829e2 --- /dev/null +++ b/os/net/security/tinydtls @@ -0,0 +1 @@ +Subproject commit 5ec7ad12984eebf22a7eb5d779f24945db4829e2 diff --git a/os/services/ip64/ip64-dhcpc.c b/os/services/ip64/ip64-dhcpc.c index 3e99cd512e025d6fcfd52a889fe1565b5557fd35..8e8e286f8913bcb49eee112d9e09e2a22350af08 100644 --- a/os/services/ip64/ip64-dhcpc.c +++ b/os/services/ip64/ip64-dhcpc.c @@ -61,9 +61,9 @@ struct dhcp_msg { uint8_t options[312]; }; -#if (UIP_BUFSIZE - UIP_UDPIP_HLEN) < 548 +#if (UIP_BUFSIZE - UIP_LLH_LEN - UIP_UDPIP_HLEN) < 548 #error UIP_CONF_BUFFER_SIZE may be too small to accomodate DHCPv4 packets -#error Increase UIP_CONF_BUFFER_SIZE in your project-conf.h, platform-conf.h, or contiki-conf.h +#error Increase UIP_CONF_BUFFER_SIZE in your project-conf.h, or contiki-conf.h #error A good size is 600 bytes #endif diff --git a/os/services/ip64/ip64-slip-interface.c b/os/services/ip64/ip64-slip-interface.c index 7ad4d4789b991e7832c6cdae97da0ad0adce2990..10422f2c7d94136e84bf33957e465b02e2e6b68a 100644 --- a/os/services/ip64/ip64-slip-interface.c +++ b/os/services/ip64/ip64-slip-interface.c @@ -57,24 +57,24 @@ static void input_callback(void) { /*PRINTF("SIN: %u\n", uip_len);*/ - if(uip_buf[0] == '!') { - PRINTF("Got configuration message of type %c\n", uip_buf[1]); + if(uip_buf[UIP_LLH_LEN] == '!') { + PRINTF("Got configuration message of type %c\n", uip_buf[UIP_LLH_LEN + 1]); uip_clear_buf(); #if 0 - if(uip_buf[1] == 'P') { + if(uip_buf[UIP_LLH_LEN + 1] == 'P') { uip_ipaddr_t prefix; /* Here we set a prefix !!! */ memset(&prefix, 0, 16); - memcpy(&prefix, &uip_buf[2], 8); + memcpy(&prefix, &uip_buf[UIP_LLH_LEN + 2], 8); PRINTF("Setting prefix "); PRINT6ADDR(&prefix); PRINTF("\n"); set_prefix_64(&prefix); } #endif - } else if(uip_buf[0] == '?') { - PRINTF("Got request message of type %c\n", uip_buf[1]); - if(uip_buf[1] == 'M') { + } else if(uip_buf[UIP_LLH_LEN] == '?') { + PRINTF("Got request message of type %c\n", uip_buf[UIP_LLH_LEN + 1]); + if(uip_buf[UIP_LLH_LEN + 1] == 'M') { const char *hexchar = "0123456789abcdef"; int j; /* this is just a test so far... just to see if it works */ @@ -84,8 +84,7 @@ input_callback(void) uip_buf[3 + j * 2] = hexchar[uip_lladdr.addr[j] & 15]; } uip_len = 18; - slip_send(); - + slip_write(uip_buf, uip_len); } uip_clear_buf(); } else { @@ -147,6 +146,3 @@ const struct uip_fallback_interface ip64_slip_interface = { init, output }; /*---------------------------------------------------------------------------*/ - - - diff --git a/os/services/ipso-objects/Makefile.ipso-objects b/os/services/ipso-objects/Makefile.ipso-objects deleted file mode 100644 index 21c56fed04844d0564cae026fd28129f2cdf3b88..0000000000000000000000000000000000000000 --- a/os/services/ipso-objects/Makefile.ipso-objects +++ /dev/null @@ -1 +0,0 @@ -CFLAGS += -DWITH_IPSO=1 diff --git a/os/services/ipso-objects/ipso-blockwise-test.c b/os/services/ipso-objects/ipso-blockwise-test.c new file mode 100644 index 0000000000000000000000000000000000000000..3a557de2bce9c49f2d2ee30a3ff9804c50b1e5ce --- /dev/null +++ b/os/services/ipso-objects/ipso-blockwise-test.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \addtogroup ipso-objects + * @{ + * + * Code to test blockwise transfer together with the LWM2M-engine. + * This object tests get with BLOCK2 and put with BLOCK1. + * + */ + +#include "lwm2m-engine.h" +#include "coap.h" +#include <string.h> + +#define DEBUG 0 +#if DEBUG +#include <stdio.h> +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +static lwm2m_object_instance_t reg_object; +static char junk[64]; + +static const lwm2m_resource_id_t resources[] = + { + RO(10000), + RO(11000), + RW(11001) + }; + +#define LEN 900 + +static lwm2m_status_t +opaque_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx, int num_to_write) +{ + int i; + PRINTF("opaque-stream callback num_to_write: %d off: %d outlen: %d\n", + num_to_write, ctx->offset, ctx->outbuf->len); + for(i = 0; i < num_to_write; i++) { + ctx->outbuf->buffer[i + ctx->outbuf->len] = '0' + (i & 31); + if(i + ctx->offset == LEN) break; + } + ctx->outbuf->len += i; + if(ctx->offset + i < LEN) { + ctx->writer_flags |= WRITER_HAS_MORE; + } + return LWM2M_STATUS_OK; +} + +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) +{ + uint32_t num; + uint8_t more; + uint16_t size; + uint32_t offset; + + char *str = "just a string"; + + PRINTF("Got request at: %d/%d/%d lv:%d\n", ctx->object_id, ctx->object_instance_id, ctx->resource_id, ctx->level); + + if(ctx->level == 1) { + /* Should not happen */ + return LWM2M_STATUS_ERROR; + } + if(ctx->level == 2) { + /* This is a get whole object - or write whole object */ + return LWM2M_STATUS_ERROR; + } + + if(ctx->operation == LWM2M_OP_READ) { +#if DEBUG + if(coap_get_header_block2(ctx->request, &num, &more, &size, &offset)) { + PRINTF("CoAP BLOCK2: %d/%d/%d offset:%d\n", num, more, size, offset); + } +#endif + + switch(ctx->resource_id) { + case 10000: + lwm2m_object_write_string(ctx, str, strlen(str)); + break; + case 11000: + case 11001: + PRINTF("Preparing object write\n"); + lwm2m_object_write_opaque_stream(ctx, LEN, opaque_callback); + break; + default: + return LWM2M_STATUS_NOT_FOUND; + } + } else if(ctx->operation == LWM2M_OP_WRITE) { + if(coap_get_header_block1(ctx->request, &num, &more, &size, &offset)) { + PRINTF("CoAP BLOCK1: %d/%d/%d offset:%d\n", num, more, size, offset); + coap_set_header_block1(ctx->response, num, 0, size); + } + } + return LWM2M_STATUS_OK; +} + +void +ipso_blockwise_test_init(void) +{ + int i; + PRINTF("Starting blockwise\n"); + reg_object.object_id = 4711; + reg_object.instance_id = 0; + reg_object.resource_ids = resources; + reg_object.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + reg_object.callback = lwm2m_callback; + + for(i = 0; i < sizeof(junk); i++) { + junk[i] = '0' + i; + } + junk[i - 1] = 0; + + lwm2m_engine_add_object(®_object); +} +/** @} */ diff --git a/os/services/ipso-objects/ipso-button.c b/os/services/ipso-objects/ipso-button.c index adda46d1e31d04f3d202f6c1e4788bfc777524aa..7993cbbb39b02a720274d28d042b82f29055ddda 100644 --- a/os/services/ipso-objects/ipso-button.c +++ b/os/services/ipso-objects/ipso-button.c @@ -36,6 +36,7 @@ /** * \file * Implementation of OMA LWM2M / IPSO button as a digital input + * NOTE: only works with a Contiki Button Sensor (not for Standalone) * \author * Joakim Eriksson <joakime@sics.se> * Niclas Finne <nfi@sics.se> @@ -44,7 +45,6 @@ #include "contiki.h" #include "lwm2m-object.h" #include "lwm2m-engine.h" -#include "coap-engine.h" #define DEBUG 0 #if DEBUG @@ -54,59 +54,98 @@ #define PRINTF(...) #endif +#define IPSO_INPUT_STATE 5500 +#define IPSO_INPUT_COUNTER 5501 +#define IPSO_INPUT_DEBOUNCE 5503 +#define IPSO_INPUT_EDGE_SEL 5504 +#define IPSO_INPUT_CTR_RESET 5505 +#define IPSO_INPUT_SENSOR_TYPE 5751 + #if PLATFORM_HAS_BUTTON +#if PLATFORM_SUPPORTS_BUTTON_HAL +#include "dev/button-hal.h" +#else #include "dev/button-sensor.h" +#define IPSO_BUTTON_SENSOR button_sensor +static struct etimer timer; +#endif PROCESS(ipso_button_process, "ipso-button"); #endif /* PLATFORM_HAS_BUTTON */ + +static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx); + static int input_state = 0; -static int polarity = 0; static int32_t counter = 0; -static int32_t edge_selection = 3; +static int32_t edge_selection = 3; /* both */ static int32_t debounce_time = 10; + +static const lwm2m_resource_id_t resources[] = { + RO(IPSO_INPUT_STATE), RO(IPSO_INPUT_COUNTER), + RW(IPSO_INPUT_DEBOUNCE), RW(IPSO_INPUT_EDGE_SEL), EX(IPSO_INPUT_CTR_RESET), + RO(IPSO_INPUT_SENSOR_TYPE) +}; + +/* Only support for one button for now */ +static lwm2m_object_instance_t reg_object = { + .object_id = 3200, + .instance_id = 0, + .resource_ids = resources, + .resource_count = sizeof(resources) / sizeof(lwm2m_resource_id_t), + .callback = lwm2m_callback, +}; + /*---------------------------------------------------------------------------*/ static int -read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) +read_state(void) { - int value; - if(polarity == 0) { - value = input_state ? 1 : 0; - } else { - value = input_state ? 0 : 1; - } - PRINTF("Read button state (polarity=%d, state=%d): %d\n", - polarity, input_state, value); - return ctx->writer->write_boolean(ctx, outbuf, outsize, value); + PRINTF("Read button state: %d\n", input_state); + return input_state; } /*---------------------------------------------------------------------------*/ -static int -reset_counter(lwm2m_context_t *ctx, const uint8_t *arg, size_t len, - uint8_t *outbuf, size_t outlen) +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) { - counter = 0; - return 0; + if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case IPSO_INPUT_STATE: + lwm2m_object_write_int(ctx, read_state()); + break; + case IPSO_INPUT_COUNTER: + lwm2m_object_write_int(ctx, counter); + break; + case IPSO_INPUT_DEBOUNCE: + lwm2m_object_write_int(ctx, debounce_time); + break; + case IPSO_INPUT_EDGE_SEL: + lwm2m_object_write_int(ctx, edge_selection); + break; + case IPSO_INPUT_SENSOR_TYPE: + lwm2m_object_write_string(ctx, "button", strlen("button")); + break; + default: + return LWM2M_STATUS_ERROR; + } + } else if(ctx->operation == LWM2M_OP_EXECUTE) { + if(ctx->resource_id == IPSO_INPUT_CTR_RESET) { + counter = 0; + } else { + return LWM2M_STATUS_ERROR; + } + } + return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ -LWM2M_RESOURCES(button_resources, - LWM2M_RESOURCE_CALLBACK(5500, { read_state, NULL, NULL }), - LWM2M_RESOURCE_INTEGER_VAR(5501, &counter), - LWM2M_RESOURCE_BOOLEAN_VAR(5502, &polarity), - LWM2M_RESOURCE_INTEGER_VAR(5503, &debounce_time), - LWM2M_RESOURCE_INTEGER_VAR(5504, &edge_selection), - LWM2M_RESOURCE_CALLBACK(5505, { NULL, NULL, reset_counter }), - LWM2M_RESOURCE_STRING(5751, "Button") - ); -LWM2M_INSTANCES(button_instances, - LWM2M_INSTANCE(0, button_resources)); -LWM2M_OBJECT(button, 3200, button_instances); -/*---------------------------------------------------------------------------*/ void ipso_button_init(void) { /* register this device and its handlers - the handlers automatically sends in the object to handle */ - lwm2m_engine_register_object(&button); + lwm2m_engine_add_object(®_object); #if PLATFORM_HAS_BUTTON process_start(&ipso_button_process, NULL); @@ -116,24 +155,39 @@ ipso_button_init(void) #if PLATFORM_HAS_BUTTON PROCESS_THREAD(ipso_button_process, ev, data) { - static struct etimer timer; - int32_t time; - PROCESS_BEGIN(); - SENSORS_ACTIVATE(button_sensor); +#if !PLATFORM_SUPPORTS_BUTTON_HAL + SENSORS_ACTIVATE(IPSO_BUTTON_SENSOR); +#endif while(1) { PROCESS_WAIT_EVENT(); - if(ev == sensors_event && data == &button_sensor) { +#if PLATFORM_SUPPORTS_BUTTON_HAL + if(ev == button_hal_press_event) { + input_state = 1; + counter++; + if((edge_selection & 2) != 0) { + lwm2m_notify_object_observers(®_object, IPSO_INPUT_STATE); + } + lwm2m_notify_object_observers(®_object, IPSO_INPUT_COUNTER); + } else if(ev == button_hal_release_event) { + input_state = 0; + if((edge_selection & 1) != 0) { + lwm2m_notify_object_observers(®_object, IPSO_INPUT_STATE); + } + } +#else /* PLATFORM_SUPPORTS_BUTTON_HAL */ + if(ev == sensors_event && data == &IPSO_BUTTON_SENSOR) { if(!input_state) { + int32_t time; input_state = 1; counter++; if((edge_selection & 2) != 0) { - lwm2m_object_notify_observers(&button, "/0/5500"); + lwm2m_notify_object_observers(®_object, IPSO_INPUT_STATE); } - lwm2m_object_notify_observers(&button, "/0/5501"); + lwm2m_notify_object_observers(®_object, IPSO_INPUT_COUNTER); time = (debounce_time * CLOCK_SECOND / 1000); if(time < 1) { @@ -144,16 +198,17 @@ PROCESS_THREAD(ipso_button_process, ev, data) } else if(ev == PROCESS_EVENT_TIMER && data == &timer) { if(!input_state) { /* Button is not in pressed state */ - } else if(button_sensor.value(0) != 0) { + } else if(IPSO_BUTTON_SENSOR.value(0) != 0) { /* Button is still pressed */ etimer_reset(&timer); } else { input_state = 0; if((edge_selection & 1) != 0) { - lwm2m_object_notify_observers(&button, "/0/5500"); + lwm2m_notify_object_observers(®_object, IPSO_INPUT_STATE); } } } +#endif /* PLATFORM_SUPPORTS_BUTTON_HAL */ } PROCESS_END(); diff --git a/os/services/ipso-objects/ipso-control-template.c b/os/services/ipso-objects/ipso-control-template.c new file mode 100644 index 0000000000000000000000000000000000000000..23b53ef0618cc4622c36b5aa7c3af7c3805db748 --- /dev/null +++ b/os/services/ipso-objects/ipso-control-template.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \addtogroup ipso-objects + * @{ + * + */ + +/** + * \file + * Implementation of OMA LWM2M / IPSO control template. + * Useful for implementing controllable objects + * \author + * Joakim Eriksson <joakime@sics.se> + * Niclas Finne <nfi@sics.se> + */ +#include "ipso-control-template.h" +#include "lwm2m-engine.h" +#include "coap-timer.h" +#include <inttypes.h> +#include <string.h> + +#define DEBUG 0 +#if DEBUG +#include <stdio.h> +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#define IPSO_ONOFF 5850 +#define IPSO_DIMMER 5851 +#define IPSO_ON_TIME 5852 + +static const lwm2m_resource_id_t resources[] = + { + RW(IPSO_ONOFF), + RW(IPSO_DIMMER), + RW(IPSO_ON_TIME) + }; +/*---------------------------------------------------------------------------*/ +lwm2m_status_t +ipso_control_set_on(ipso_control_t *control, uint8_t onoroff) +{ + uint8_t v; + + if(onoroff) { + v = control->value & 0x7f; + if(v == 0) { + v = 100; + } + } else { + v = 0; + } + + return ipso_control_set_value(control, v); +} +/*---------------------------------------------------------------------------*/ +lwm2m_status_t +ipso_control_set_value(ipso_control_t *control, uint8_t value) +{ + lwm2m_status_t status = LWM2M_STATUS_OK; + int was_on; + + was_on = ipso_control_is_on(control); + + if(value == 0) { + if(was_on) { + /* Turn off */ + status = control->set_value(control, 0); + if(status == LWM2M_STATUS_OK) { + control->value &= 0x7f; + control->on_time += + (coap_timer_uptime() - control->last_on_time) / 1000; + } + } + } else { + /* Restrict value between 0 - 100 */ + if(value > 100) { + value = 100; + } + value |= 0x80; + + if(value != control->value) { + status = control->set_value(control, value & 0x7f); + if(status == LWM2M_STATUS_OK) { + control->value = value; + if(! was_on) { + control->last_on_time = coap_timer_uptime(); + } + } + } + } + return status; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, lwm2m_context_t *ctx) +{ + ipso_control_t *control; + int32_t v; + + /* Here we cast to our sensor-template struct */ + control = (ipso_control_t *)object; + + if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case IPSO_ONOFF: + v = ipso_control_is_on(control) ? 1 : 0; + break; + case IPSO_DIMMER: + v = ipso_control_get_value(control); + break; + case IPSO_ON_TIME: + v = control->on_time; + if(ipso_control_is_on(control)) { + v += (coap_timer_uptime() - control->last_on_time) / 1000; + } + PRINTF("ON-TIME: %"PRId32" (last on: %"PRIu32"\n", v, control->on_time); + break; + default: + return LWM2M_STATUS_ERROR; + } + lwm2m_object_write_int(ctx, v); + return LWM2M_STATUS_OK; + + } else if(ctx->operation == LWM2M_OP_WRITE) { + switch(ctx->resource_id) { + case IPSO_ONOFF: + if(lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v) == 0) { + return LWM2M_STATUS_ERROR; + } + return ipso_control_set_on(control, v > 0); + case IPSO_DIMMER: + if(lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v) == 0) { + return LWM2M_STATUS_ERROR; + } + if(v < 0) { + v = 0; + } else if(v > 100) { + v = 100; + } + return ipso_control_set_value(control, v & 0xff); + case IPSO_ON_TIME: + if(lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v) == 0) { + return LWM2M_STATUS_ERROR; + } + + if(v == 0) { + control->on_time = 0; + control->last_on_time = coap_timer_uptime(); + return LWM2M_STATUS_OK; + } else { + /* Only allowed to write 0 to reset ontime */ + return LWM2M_STATUS_FORBIDDEN; + } + break; + default: + return LWM2M_STATUS_ERROR; + } + } else { + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } +} +/*---------------------------------------------------------------------------*/ +int +ipso_control_add(ipso_control_t *control) +{ + control->reg_object.resource_ids = resources; + control->reg_object.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + + control->reg_object.callback = lwm2m_callback; + return lwm2m_engine_add_object(&control->reg_object); +} +/*---------------------------------------------------------------------------*/ +int +ipso_control_remove(ipso_control_t *control) +{ + lwm2m_engine_remove_object(&control->reg_object); + return 1; +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/services/ipso-objects/ipso-control-template.h b/os/services/ipso-objects/ipso-control-template.h new file mode 100644 index 0000000000000000000000000000000000000000..dfbd7076b073dd7894c12d50caf210fdb47ea86a --- /dev/null +++ b/os/services/ipso-objects/ipso-control-template.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \addtogroup ipso-objects + * @{ + * + */ + +/** + * \file + * Implementation of OMA LWM2M / IPSO sensor template. + * \author + * Joakim Eriksson <joakime@sics.se> + * Niclas Finne <nfi@sics.se> + */ + +#ifndef IPSO_CONTROL_TEMPLATE_H_ +#define IPSO_CONTROL_TEMPLATE_H_ + +#include "lwm2m-engine.h" + +typedef struct ipso_control ipso_control_t; + +#define IPSO_CONTROL_USE_DIMMER 0x01 + +typedef lwm2m_status_t (*ipso_control_set_value_t)(ipso_control_t *control, + uint8_t v); + +/* Values of the IPSO control object */ +struct ipso_control { + lwm2m_object_instance_t reg_object; + uint8_t flags; + uint8_t value; /* used to emulate on/off and dim-value */ + uint32_t on_time; /* on-time in seconds */ + uint64_t last_on_time; + ipso_control_set_value_t set_value; +}; + +#define IPSO_CONTROL(name, oid, iid, setv) \ + static ipso_control_t name = { \ + .reg_object.object_id = oid, \ + .reg_object.instance_id = iid, \ + .set_value = setv \ + } + +int ipso_control_add(ipso_control_t *control); +int ipso_control_remove(ipso_control_t *control); + +static inline uint16_t +ipso_control_get_object_id(const ipso_control_t *control) +{ + return control->reg_object.object_id; +} + +static inline uint16_t +ipso_control_get_instance_id(const ipso_control_t *control) +{ + return control->reg_object.instance_id; +} + +static inline uint8_t +ipso_control_is_on(const ipso_control_t *control) +{ + return (control->value & 0x80) != 0; +} + +static inline uint8_t +ipso_control_get_value(const ipso_control_t *control) +{ + return (control->value & 0x80) != 0 ? (control->value & 0x7f) : 0; +} + +lwm2m_status_t ipso_control_set_on(ipso_control_t *control, uint8_t onoroff); + +lwm2m_status_t ipso_control_set_value(ipso_control_t *control, uint8_t dimm_value); + +#endif /* IPSO_CONTROL_TEMPLATE_H_ */ +/** @} */ diff --git a/os/services/ipso-objects/ipso-leds-control.c b/os/services/ipso-objects/ipso-leds-control.c index 38f150f39cf635ec0f5676e3dad1a8adda2c861a..2c64da3282d351feec8687221744cf549659c81a 100644 --- a/os/services/ipso-objects/ipso-leds-control.c +++ b/os/services/ipso-objects/ipso-leds-control.c @@ -44,7 +44,7 @@ #include "lwm2m-object.h" #include "lwm2m-engine.h" -#include "coap-engine.h" +#include "ipso-control-template.h" #include "dev/leds.h" #include <stdint.h> @@ -56,145 +56,41 @@ #define PRINTF(...) #endif +#if LEDS_LEGACY_API #if LEDS_ALL & LEDS_BLUE || LEDS_ALL & LEDS_RED || LEDS_ALL & LEDS_BLUE #define LEDS_CONTROL_NUMBER (((LEDS_ALL & LEDS_BLUE) ? 1 : 0) + ((LEDS_ALL & LEDS_RED) ? 1 : 0) + ((LEDS_ALL & LEDS_GREEN) ? 1 : 0)) #else #define LEDS_CONTROL_NUMBER 1 #endif +#else /* LEDS_LEGACY_API */ +#define LEDS_CONTROL_NUMBER LEDS_COUNT +#endif /* LEDS_LEGACY_API */ -struct led_state { - unsigned long last_on_time; - uint32_t total_on_time; - uint8_t is_on; +typedef struct led_state { + ipso_control_t control; uint8_t led_value; -}; +} led_state_t; -static struct led_state states[LEDS_CONTROL_NUMBER]; -static lwm2m_instance_t leds_control_instances[LEDS_CONTROL_NUMBER]; +static led_state_t leds_controls[LEDS_CONTROL_NUMBER]; /*---------------------------------------------------------------------------*/ -static int -read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - uint8_t idx = ctx->object_instance_index; - if(idx >= LEDS_CONTROL_NUMBER) { - return 0; - } - return ctx->writer->write_boolean(ctx, outbuf, outsize, - states[idx].is_on ? 1 : 0); -} -/*---------------------------------------------------------------------------*/ -static int -write_state(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) +static lwm2m_status_t +set_value(ipso_control_t *control, uint8_t value) { - int value; - size_t len; +#if PLATFORM_HAS_LEDS || LEDS_COUNT + led_state_t *state; - uint8_t idx = ctx->object_instance_index; - if(idx >= LEDS_CONTROL_NUMBER) { - return 0; - } + state = (led_state_t *)control; - len = ctx->reader->read_boolean(ctx, inbuf, insize, &value); - if(len > 0) { - if(value) { - if(!states[idx].is_on) { - states[idx].is_on = 1; - states[idx].last_on_time = clock_seconds(); -#if PLATFORM_HAS_LEDS - leds_on(states[idx].led_value); -#endif /* PLATFORM_HAS_LEDS */ - } - } else if(states[idx].is_on) { - states[idx].total_on_time += clock_seconds() - states[idx].last_on_time; - states[idx].is_on = 0; -#if PLATFORM_HAS_LEDS - leds_off(states[idx].led_value); -#endif /* PLATFORM_HAS_LEDS */ - } + if(value) { + leds_on(state->led_value); } else { - PRINTF("IPSO leds control - ignored illegal write to on/off\n"); - } - return len; -} -/*---------------------------------------------------------------------------*/ -static char * -get_color(int value) { - switch(value) { - case LEDS_GREEN: - return "Green"; - case LEDS_RED: - return "Red"; - case LEDS_BLUE: - return "Blue"; - } - return "None"; -} - -static int -read_color(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - char *value; - uint8_t idx = ctx->object_instance_index; - if(idx >= LEDS_CONTROL_NUMBER) { - return 0; - } - value = get_color(states[idx].led_value); - return ctx->writer->write_string(ctx, outbuf, outsize, - value, strlen(value)); -} -/*---------------------------------------------------------------------------*/ -static int -read_on_time(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - unsigned long now; - uint8_t idx = ctx->object_instance_index; - if(idx >= LEDS_CONTROL_NUMBER) { - return 0; - } - - if(states[idx].is_on) { - /* Update the on time */ - now = clock_seconds(); - states[idx].total_on_time += now - states[idx].last_on_time; - states[idx].last_on_time = now; - } - return ctx->writer->write_int(ctx, outbuf, outsize, - (int32_t)states[idx].total_on_time); -} -/*---------------------------------------------------------------------------*/ -static int -write_on_time(lwm2m_context_t *ctx, - const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) -{ - int32_t value; - size_t len; - uint8_t idx = ctx->object_instance_index; - if(idx >= LEDS_CONTROL_NUMBER) { - return 0; + leds_off(state->led_value); } +#endif /* PLATFORM_HAS_LEDS */ - len = ctx->reader->read_int(ctx, inbuf, insize, &value); - if(len > 0 && value == 0) { - PRINTF("IPSO leds control - reset On Time\n"); - states[idx].total_on_time = 0; - if(states[idx].is_on) { - states[idx].last_on_time = clock_seconds(); - } - } else { - PRINTF("IPSO leds control - ignored illegal write to On Time\n"); - } - return len; + return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ -LWM2M_RESOURCES(leds_control_resources, - LWM2M_RESOURCE_CALLBACK(5850, { read_state, write_state, NULL }), - LWM2M_RESOURCE_CALLBACK(5706, { read_color, NULL, NULL }), - LWM2M_RESOURCE_CALLBACK(5852, { read_on_time, write_on_time, NULL }) - ); -LWM2M_OBJECT(leds_control, 3311, leds_control_instances); -/*---------------------------------------------------------------------------*/ static int bit_no(int bit) { @@ -212,23 +108,23 @@ bit_no(int bit) } return 0; } - +/*---------------------------------------------------------------------------*/ void ipso_leds_control_init(void) { - lwm2m_instance_t template = LWM2M_INSTANCE(0, leds_control_resources); + ipso_control_t *c; int i; /* Initialize the instances */ for(i = 0; i < LEDS_CONTROL_NUMBER; i++) { - leds_control_instances[i] = template; - leds_control_instances[i].id = i; - states[i].led_value = bit_no(i); + c = &leds_controls[i].control; + c->reg_object.object_id = 3311; + c->reg_object.instance_id = i; + c->set_value = set_value; + leds_controls[i].led_value = bit_no(i); + ipso_control_add(c); } - /* register this device and its handlers - the handlers automatically - sends in the object to handle */ - lwm2m_engine_register_object(&leds_control); PRINTF("IPSO leds control initialized with %u instances\n", LEDS_CONTROL_NUMBER); } diff --git a/os/services/ipso-objects/ipso-light-control.c b/os/services/ipso-objects/ipso-light-control.c index 02c4b9be2cad561b780caf98b5bc9d05eb75f60b..97733b6292b31b96855eca1c3ac158193c1cf137 100644 --- a/os/services/ipso-objects/ipso-light-control.c +++ b/os/services/ipso-objects/ipso-light-control.c @@ -45,138 +45,29 @@ #include "ipso-objects.h" #include "lwm2m-object.h" #include "lwm2m-engine.h" +#include "ipso-control-template.h" #ifdef IPSO_LIGHT_CONTROL extern const struct ipso_objects_actuator IPSO_LIGHT_CONTROL; #endif /* IPSO_LIGHT_CONTROL */ -/*---------------------------------------------------------------------------*/ -static unsigned long last_on_time; -static uint32_t total_on_time; -static int dim_level = 0; -static uint8_t is_on = 0; -/*---------------------------------------------------------------------------*/ -static int -read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - return ctx->writer->write_boolean(ctx, outbuf, outsize, is_on ? 1 : 0); -} -/*---------------------------------------------------------------------------*/ -static int -write_state(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) -{ - int value; - size_t len; - len = ctx->reader->read_boolean(ctx, inbuf, insize, &value); - if(len > 0) { - if(value) { - if(!is_on) { - is_on = 1; - last_on_time = clock_seconds(); - } - } else { - if(is_on) { - total_on_time += clock_seconds() - last_on_time; - is_on = 0; - } - } -#ifdef IPSO_LIGHT_CONTROL - if(IPSO_LIGHT_CONTROL.set_on) { - IPSO_LIGHT_CONTROL.set_on(value); - } else if(IPSO_LIGHT_CONTROL.set_dim_level) { - dim_level = value ? 100 : 0; - IPSO_LIGHT_CONTROL.set_dim_level(dim_level); - } -#endif /* IPSO_LIGHT_CONTROL */ - } - return len; -} -/*---------------------------------------------------------------------------*/ -static int -read_dim(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - return ctx->writer->write_int(ctx, outbuf, outsize, dim_level); -} -/*---------------------------------------------------------------------------*/ -static int -write_dim(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) -{ - int32_t value; - size_t len; +static lwm2m_status_t set_value(ipso_control_t *control, uint8_t value); - len = ctx->reader->read_int(ctx, inbuf, insize, &value); - if(len > 0) { - if(value < 0) { - value = 0; - } else if(value > 100) { - value = 100; - } - - dim_level = value; - if(value > 0) { - if(!is_on) { - is_on = 1; - last_on_time = clock_seconds(); - } - } else { - if(is_on) { - total_on_time += clock_seconds() - last_on_time; - is_on = 0; - } - } -#ifdef IPSO_LIGHT_CONTROL - if(IPSO_LIGHT_CONTROL.set_dim_level) { - IPSO_LIGHT_CONTROL.set_dim_level(dim_level); - } else if(IPSO_LIGHT_CONTROL.set_on) { - IPSO_LIGHT_CONTROL.set_on(is_on); - } -#endif /* IPSO_LIGHT_CONTROL */ - } - return len; -} -/*---------------------------------------------------------------------------*/ -static int -read_on_time(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - unsigned long now; - if(is_on) { - /* Update the on time */ - now = clock_seconds(); - total_on_time += now - last_on_time; - last_on_time = now; - } - return ctx->writer->write_int(ctx, outbuf, outsize, (int32_t)total_on_time); -} +IPSO_CONTROL(light_control, 3311, 0, set_value); /*---------------------------------------------------------------------------*/ -static int -write_on_time(lwm2m_context_t *ctx, - const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) +static lwm2m_status_t +set_value(ipso_control_t *control, uint8_t value) { - int32_t value; - size_t len; - - len = ctx->reader->read_int(ctx, inbuf, insize, &value); - if(len > 0 && value == 0) { - total_on_time = 0; - if(is_on) { - last_on_time = clock_seconds(); - } +#ifdef IPSO_LIGHT_CONTROL + if(IPSO_LIGHT_CONTROL.set_dim_level) { + IPSO_LIGHT_CONTROL.set_dim_level(value); + } else if(IPSO_LIGHT_CONTROL.set_on) { + IPSO_LIGHT_CONTROL.set_on(value); } - return len; +#endif /* IPSO_LIGHT_CONTROL */ + return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ -LWM2M_RESOURCES(light_control_resources, - LWM2M_RESOURCE_CALLBACK(5850, { read_state, write_state, NULL }), - LWM2M_RESOURCE_CALLBACK(5851, { read_dim, write_dim, NULL }), - LWM2M_RESOURCE_CALLBACK(5852, { read_on_time, write_on_time, NULL }), - ); -LWM2M_INSTANCES(light_control_instances, - LWM2M_INSTANCE(0, light_control_resources)); -LWM2M_OBJECT(light_control, 3311, light_control_instances); -/*---------------------------------------------------------------------------*/ void ipso_light_control_init(void) { @@ -184,19 +75,15 @@ ipso_light_control_init(void) if(IPSO_LIGHT_CONTROL.init) { IPSO_LIGHT_CONTROL.init(); } - if(IPSO_LIGHT_CONTROL.is_on) { - is_on = IPSO_LIGHT_CONTROL.is_on(); - } if(IPSO_LIGHT_CONTROL.get_dim_level) { - dim_level = IPSO_LIGHT_CONTROL.get_dim_level(); - if(dim_level > 0 && IPSO_LIGHT_CONTROL.is_on == NULL) { - is_on = 1; - } + ipso_control_set_value(&light_control, + IPSO_LIGHT_CONTROL.get_dim_level()); + } else if(IPSO_LIGHT_CONTROL.is_on) { + ipso_control_set_on(&light_control, IPSO_LIGHT_CONTROL.is_on()); } #endif /* IPSO_LIGHT_CONTROL */ - last_on_time = clock_seconds(); - lwm2m_engine_register_object(&light_control); + ipso_control_add(&light_control); } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/ipso-objects/ipso-objects.c b/os/services/ipso-objects/ipso-objects.c index 1e8243f942f399995462e71f2149a9ee732ba31f..f8538ee43bfec42e817ef24913a16941585534b0 100644 --- a/os/services/ipso-objects/ipso-objects.c +++ b/os/services/ipso-objects/ipso-objects.c @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup ipso-objects * @{ */ @@ -42,6 +42,7 @@ */ #include "contiki.h" +#include "dev/leds.h" #include "ipso-objects.h" /*---------------------------------------------------------------------------*/ void @@ -58,7 +59,7 @@ ipso_objects_init(void) #ifdef IPSO_LIGHT_CONTROL ipso_light_control_init(); -#elif PLATFORM_HAS_LEDS +#elif PLATFORM_HAS_LEDS || LEDS_COUNT ipso_leds_control_init(); #endif } diff --git a/os/services/ipso-objects/ipso-objects.h b/os/services/ipso-objects/ipso-objects.h index 6b8f5c2a66cc664fb6b9fcb6c93bf74a09a176ca..92bdfd8decd1ff2da1fb7d5fff6fa2dc6ab0921f 100644 --- a/os/services/ipso-objects/ipso-objects.h +++ b/os/services/ipso-objects/ipso-objects.h @@ -37,8 +37,7 @@ * \defgroup ipso-objects An implementation of IPSO Objects * @{ * - * This application is an implementation of IPSO Objects for - * OMA Lightweight M2M. + * This is an implementation of IPSO Objects for OMA LWM2M. */ /** diff --git a/os/services/ipso-objects/ipso-sensor-template.c b/os/services/ipso-objects/ipso-sensor-template.c new file mode 100644 index 0000000000000000000000000000000000000000..bf46ed5ae985980cc40c04436a28dc07abd7c7f7 --- /dev/null +++ b/os/services/ipso-objects/ipso-sensor-template.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \addtogroup ipso-objects + * @{ + * + */ + +/** + * \file + * Implementation of OMA LWM2M / IPSO sensor template. + * \author + * Joakim Eriksson <joakime@sics.se> + * Niclas Finne <nfi@sics.se> + */ +#include "ipso-sensor-template.h" +#include "lwm2m-engine.h" +#include <string.h> +#include <stdio.h> + +#define IPSO_SENSOR_VALUE 5700 +#define IPSO_SENSOR_UNIT 5701 +#define IPSO_SENSOR_MIN_VALUE 5601 +#define IPSO_SENSOR_MAX_VALUE 5602 +#define IPSO_SENSOR_MIN_RANGE 5603 +#define IPSO_SENSOR_MAX_RANGE 5604 + +#define IPSO_SENSOR_RESET_MINMAX 5605 + +static const lwm2m_resource_id_t resources[] = + { + RO(IPSO_SENSOR_VALUE), RO(IPSO_SENSOR_UNIT), + RO(IPSO_SENSOR_MIN_VALUE), RO(IPSO_SENSOR_MAX_VALUE), + RO(IPSO_SENSOR_MIN_RANGE), RO(IPSO_SENSOR_MAX_RANGE), + EX(IPSO_SENSOR_RESET_MINMAX) + }; + +/*---------------------------------------------------------------------------*/ +static void update_last_value(ipso_sensor_value_t *sval, int32_t value, + uint8_t notify); +/*---------------------------------------------------------------------------*/ +static int init = 0; +static coap_timer_t nt; + +/* Currently support max 4 periodic sensors */ +#define MAX_PERIODIC 4 +struct periodic_sensor { + ipso_sensor_value_t *value; + uint16_t ticks_left; +} periodics[MAX_PERIODIC]; + +static void +timer_callback(coap_timer_t *timer) +{ + int i; + coap_timer_reset(timer, 1000); + + for(i = 0; i < MAX_PERIODIC; i++) { + if(periodics[i].value != NULL) { + if(periodics[i].ticks_left > 0) { + periodics[i].ticks_left--; + } else { + int32_t value; + periodics[i].ticks_left = periodics[i].value->sensor->update_interval; + if(periodics[i].value->sensor->get_value_in_millis(periodics[i].value->sensor, &value) == LWM2M_STATUS_OK) { + update_last_value(periodics[i].value, value, 1); + } + } + } + } +} + +static void +add_periodic(const ipso_sensor_t *sensor) +{ + int i; + for(i = 0; i < MAX_PERIODIC; i++) { + if(periodics[i].value == NULL) { + periodics[i].value = sensor->sensor_value; + periodics[i].ticks_left = sensor->update_interval; + return; + } + } +} +/*---------------------------------------------------------------------------*/ +static void +update_last_value(ipso_sensor_value_t *sval, int32_t value, uint8_t notify) +{ + /* No notification if this a regular read that cause the update */ + if(sval->last_value != value && notify) { + lwm2m_notify_object_observers(&sval->reg_object, IPSO_SENSOR_VALUE); + } + sval->last_value = value; + if(sval->min_value > value) { + sval->min_value = value; + lwm2m_notify_object_observers(&sval->reg_object, IPSO_SENSOR_MIN_VALUE); + } + if(sval->max_value < value) { + sval->max_value = value; + lwm2m_notify_object_observers(&sval->reg_object, IPSO_SENSOR_MAX_VALUE); + } +} +/*---------------------------------------------------------------------------*/ +static inline size_t +write_float32fix(lwm2m_context_t *ctx, int32_t value) +{ + int64_t tmp = value; + tmp = (tmp * 1024) / 1000; + return lwm2m_object_write_float32fix(ctx, (int32_t)tmp, 10); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) +{ + /* Here we cast to our sensor-template struct */ + const ipso_sensor_t *sensor; + ipso_sensor_value_t *value; + value = (ipso_sensor_value_t *) object; + sensor = value->sensor; + + /* Do the stuff */ + if(ctx->level == 1) { + /* Should not happen 3303 */ + return LWM2M_STATUS_ERROR; + } + if(ctx->level == 2) { + /* This is a get whole object - or write whole object 3303/0 */ + return LWM2M_STATUS_ERROR; + } + if(ctx->level == 3) { + /* This is a get request on 3303/0/3700 */ + /* NOW we assume a get.... which might be wrong... */ + if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case IPSO_SENSOR_UNIT: + if(sensor->unit != NULL) { + lwm2m_object_write_string(ctx, sensor->unit, strlen(sensor->unit)); + } + break; + case IPSO_SENSOR_MAX_RANGE: + write_float32fix(ctx, sensor->max_range); + break; + case IPSO_SENSOR_MIN_RANGE: + write_float32fix(ctx, sensor->min_range); + break; + case IPSO_SENSOR_MAX_VALUE: + write_float32fix(ctx, value->max_value); + break; + case IPSO_SENSOR_MIN_VALUE: + write_float32fix(ctx, value->min_value); + break; + case IPSO_SENSOR_VALUE: + if(sensor->get_value_in_millis != NULL) { + int32_t v; + if(sensor->get_value_in_millis(sensor, &v) == LWM2M_STATUS_OK) { + update_last_value(value, v, 0); + write_float32fix(ctx, value->last_value); + } + } + break; + default: + return LWM2M_STATUS_ERROR; + } + } else if(ctx->operation == LWM2M_OP_EXECUTE) { + if(ctx->resource_id == IPSO_SENSOR_RESET_MINMAX) { + value->min_value = value->last_value; + value->max_value = value->last_value; + } + } + } + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +int +ipso_sensor_add(const ipso_sensor_t *sensor) +{ + if(sensor->update_interval > 0) { + if(init == 0) { + coap_timer_set_callback(&nt, timer_callback); + coap_timer_set(&nt, 1000); + init = 1; + } + add_periodic(sensor); + } + + if(sensor->sensor_value == NULL) { + return 0; + } + sensor->sensor_value->reg_object.object_id = sensor->object_id; + sensor->sensor_value->sensor = sensor; + if(sensor->instance_id == 0) { + sensor->sensor_value->reg_object.instance_id = LWM2M_OBJECT_INSTANCE_NONE; + } else { + sensor->sensor_value->reg_object.instance_id = sensor->instance_id; + } + sensor->sensor_value->reg_object.callback = lwm2m_callback; + sensor->sensor_value->reg_object.resource_ids = resources; + sensor->sensor_value->reg_object.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + return lwm2m_engine_add_object(&sensor->sensor_value->reg_object); +} +/*---------------------------------------------------------------------------*/ +int +ipso_sensor_remove(const ipso_sensor_t *sensor) +{ + lwm2m_engine_remove_object(&sensor->sensor_value->reg_object); + return 1; +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/services/ipso-objects/ipso-sensor-template.h b/os/services/ipso-objects/ipso-sensor-template.h new file mode 100644 index 0000000000000000000000000000000000000000..375dbad7cc2969cbb74275feb41cd3385f66be42 --- /dev/null +++ b/os/services/ipso-objects/ipso-sensor-template.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \addtogroup ipso-objects + * @{ + * + */ + +/** + * \file + * Implementation of OMA LWM2M / IPSO sensor template. + * \author + * Joakim Eriksson <joakime@sics.se> + * Niclas Finne <nfi@sics.se> + */ + +#ifndef IPSO_SENSOR_TEMPLATE_H_ +#define IPSO_SENSOR_TEMPLATE_H_ + +#include "lwm2m-engine.h" + +typedef struct ipso_sensor ipso_sensor_t; + +typedef lwm2m_status_t (*ipso_sensor_get_value_millis_t)(const ipso_sensor_t *sensor, int32_t *v); + +/* Values of the IPSO object */ +typedef struct ipso_sensor_value { + lwm2m_object_instance_t reg_object; + const ipso_sensor_t *sensor; + uint8_t flags; + int32_t last_value; + int32_t min_value; + int32_t max_value; +} ipso_sensor_value_t; + +/* Meta data about an IPSO sensor object */ +struct ipso_sensor { + /* LWM2M object type */ + uint16_t object_id; + uint16_t instance_id; + /* When we read out the value we send in a context to write to */ + ipso_sensor_get_value_millis_t get_value_in_millis; + int32_t min_range; + int32_t max_range; + char *unit; + /* update interval in seconds */ + uint16_t update_interval; + ipso_sensor_value_t *sensor_value; +}; + +#define IPSO_SENSOR(name, oid, get_value, ...) \ + static ipso_sensor_value_t name##_value; \ + static const ipso_sensor_t name = { \ + .object_id = oid, \ + .sensor_value = &name##_value, \ + .get_value_in_millis = get_value, \ + __VA_ARGS__ \ + } + +int ipso_sensor_add(const ipso_sensor_t *sensor); +int ipso_sensor_remove(const ipso_sensor_t *sensor); + +#endif /* IPSO_SENSOR_TEMPLATE_H_ */ +/** @} */ diff --git a/os/services/ipso-objects/ipso-temperature.c b/os/services/ipso-objects/ipso-temperature.c index 1851245e24065211bcdf081593a9f9da7c61c283..c27d8b6ba2e170e9c3aaa4db2a3b82c43c15b24e 100644 --- a/os/services/ipso-objects/ipso-temperature.c +++ b/os/services/ipso-objects/ipso-temperature.c @@ -42,118 +42,56 @@ */ #include <stdint.h> +#include "ipso-sensor-template.h" #include "ipso-objects.h" #include "lwm2m-object.h" #include "lwm2m-engine.h" -#include "coap-engine.h" #ifdef IPSO_TEMPERATURE extern const struct ipso_objects_sensor IPSO_TEMPERATURE; #endif /* IPSO_TEMPERATURE */ #ifndef IPSO_TEMPERATURE_MIN -#define IPSO_TEMPERATURE_MIN (-50 * LWM2M_FLOAT32_FRAC) +#define IPSO_TEMPERATURE_MIN -50000 #endif #ifndef IPSO_TEMPERATURE_MAX -#define IPSO_TEMPERATURE_MAX (80 * LWM2M_FLOAT32_FRAC) +#define IPSO_TEMPERATURE_MAX 80000 #endif -static struct ctimer periodic_timer; -static int32_t min_temp; -static int32_t max_temp; -static int read_temp(int32_t *value); -/*---------------------------------------------------------------------------*/ -static int -temp(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) -{ - int32_t value; - if(read_temp(&value)) { - return ctx->writer->write_float32fix(ctx, outbuf, outsize, - value, LWM2M_FLOAT32_BITS); - } - return 0; -} -/*---------------------------------------------------------------------------*/ -LWM2M_RESOURCES(temperature_resources, - /* Temperature (Current) */ - LWM2M_RESOURCE_CALLBACK(5700, { temp, NULL, NULL }), - /* Units */ - LWM2M_RESOURCE_STRING(5701, "Cel"), - /* Min Range Value */ - LWM2M_RESOURCE_FLOATFIX(5603, IPSO_TEMPERATURE_MIN), - /* Max Range Value */ - LWM2M_RESOURCE_FLOATFIX(5604, IPSO_TEMPERATURE_MAX), - /* Min Measured Value */ - LWM2M_RESOURCE_FLOATFIX_VAR(5601, &min_temp), - /* Max Measured Value */ - LWM2M_RESOURCE_FLOATFIX_VAR(5602, &max_temp), - ); -LWM2M_INSTANCES(temperature_instances, - LWM2M_INSTANCE(0, temperature_resources)); -LWM2M_OBJECT(temperature, 3303, temperature_instances); +static lwm2m_status_t get_temp_value(const ipso_sensor_t *sensor, + int32_t *value); + +IPSO_SENSOR(temp_sensor, 3303, get_temp_value, + .max_range = IPSO_TEMPERATURE_MAX, /* milli celcius */ + .min_range = IPSO_TEMPERATURE_MIN, /* milli celcius */ + .unit = "Cel", + .update_interval = 10 + ); + /*---------------------------------------------------------------------------*/ -static int -read_temp(int32_t *value) +static lwm2m_status_t +get_temp_value(const ipso_sensor_t *s, int32_t *value) { #ifdef IPSO_TEMPERATURE - int32_t temp; if(IPSO_TEMPERATURE.read_value == NULL || - IPSO_TEMPERATURE.read_value(&temp) != 0) { - return 0; - } - - /* Convert milliCelsius to fix float */ - *value = (temp * LWM2M_FLOAT32_FRAC) / 1000; - - if(*value < min_temp) { - min_temp = *value; - lwm2m_object_notify_observers(&temperature, "/0/5601"); - } - if(*value > max_temp) { - max_temp = *value; - lwm2m_object_notify_observers(&temperature, "/0/5602"); + IPSO_TEMPERATURE.read_value(value) != 0) { + return LWM2M_STATUS_OK; } - return 1; -#else /* IPSO_TEMPERATURE */ - return 0; #endif /* IPSO_TEMPERATURE */ -} -/*---------------------------------------------------------------------------*/ -static void -handle_periodic_timer(void *ptr) -{ - static int32_t last_value = IPSO_TEMPERATURE_MIN; - int32_t v; - - /* Only notify when the value has changed since last */ - if(read_temp(&v) && v != last_value) { - last_value = v; - lwm2m_object_notify_observers(&temperature, "/0/5700"); - } - ctimer_reset(&periodic_timer); + return LWM2M_STATUS_ERROR; } /*---------------------------------------------------------------------------*/ void ipso_temperature_init(void) { - int32_t v; - min_temp = IPSO_TEMPERATURE_MAX; - max_temp = IPSO_TEMPERATURE_MIN; - #ifdef IPSO_TEMPERATURE if(IPSO_TEMPERATURE.init) { IPSO_TEMPERATURE.init(); } #endif /* IPSO_TEMPERATURE */ - /* register this device and its handlers - the handlers automatically - sends in the object to handle */ - lwm2m_engine_register_object(&temperature); - - /* update temp and min/max + notify any listeners */ - read_temp(&v); - ctimer_set(&periodic_timer, CLOCK_SECOND * 10, handle_periodic_timer, NULL); + ipso_sensor_add(&temp_sensor); } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/Makefile.lwm2m b/os/services/lwm2m/Makefile.lwm2m deleted file mode 100644 index 47c4fe5dad63b8903a96be547aa9bd277ead401c..0000000000000000000000000000000000000000 --- a/os/services/lwm2m/Makefile.lwm2m +++ /dev/null @@ -1 +0,0 @@ -CFLAGS += -DHAVE_OMA_LWM2M=1 diff --git a/os/services/lwm2m/lwm2m-device.c b/os/services/lwm2m/lwm2m-device.c index a911c7c4aae3b421c392bf3050d70b35ce16e048..4183c59ca257b6758f4b2c71d3e98742dc30c89c 100644 --- a/os/services/lwm2m/lwm2m-device.c +++ b/os/services/lwm2m/lwm2m-device.c @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ @@ -44,109 +44,182 @@ #include "lwm2m-object.h" #include "lwm2m-device.h" #include "lwm2m-engine.h" +#include <string.h> -#define DEBUG 0 -#if DEBUG -#include <stdio.h> -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-dev" +#define LOG_LEVEL LOG_LEVEL_LWM2M + +static const lwm2m_resource_id_t resources[] = + { RO(LWM2M_DEVICE_MANUFACTURER_ID), + RO(LWM2M_DEVICE_MODEL_NUMBER_ID), + RO(LWM2M_DEVICE_SERIAL_NUMBER_ID), + RO(LWM2M_DEVICE_FIRMWARE_VERSION_ID), + RO(LWM2M_DEVICE_AVAILABLE_POWER_SOURCES), /* Multi-resource-instance */ + RO(LWM2M_DEVICE_POWER_SOURCE_VOLTAGE), /* Multi-resource-instance */ + RO(LWM2M_DEVICE_POWER_SOURCE_CURRENT), /* Multi-resource-instance */ + RO(LWM2M_DEVICE_TYPE_ID), + EX(LWM2M_DEVICE_REBOOT_ID), + RW(LWM2M_DEVICE_TIME_ID), + EX(LWM2M_DEVICE_FACTORY_DEFAULT_ID), + }; + +#ifndef LWM2M_DEVICE_MANUFACTURER +#define LWM2M_DEVICE_MANUFACTURER "RISE SICS" +#endif +#ifndef LWM2M_DEVICE_MODEL_NUMBER +#define LWM2M_DEVICE_MODEL_NUMBER "1" +#endif +#ifndef LWM2M_DEVICE_SERIAL_NUMBER +#define LWM2M_DEVICE_SERIAL_NUMBER "1" +#endif +#ifndef LWM2M_DEVICE_FIRMWARE_VERSION +#define LWM2M_DEVICE_FIRMWARE_VERSION CONTIKI_VERSION +#endif +#ifndef LWM2M_DEVICE_TYPE +#define LWM2M_DEVICE_TYPE "Contiki-NG LWM2M" +#endif + +/* All three must be defined */ +#ifndef LWM2M_DEVICE_POWER_AVAILABLE +#define LWM2M_DEVICE_POWER_AVAILABLE {1,5} +#define LWM2M_DEVICE_POWER_VOLTAGE {2500,5000} +#define LWM2M_DEVICE_POWER_CURRENT {500,1000} #endif static int32_t time_offset = 0; + +/* Internal battery and USB - just for test...*/ +static uint16_t power_avail[] = LWM2M_DEVICE_POWER_AVAILABLE; +static uint16_t power_voltage[] = LWM2M_DEVICE_POWER_VOLTAGE; +static uint16_t power_current[] = LWM2M_DEVICE_POWER_CURRENT; /*---------------------------------------------------------------------------*/ -static int -read_lwtime(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize) +int32_t +lwm2m_device_get_time(void) { - return ctx->writer->write_int(ctx, outbuf, outsize, - time_offset + clock_seconds()); + return coap_timer_seconds() + time_offset; } /*---------------------------------------------------------------------------*/ -static int -set_lwtime(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) +void +lwm2m_device_set_time(int32_t time) { - /* assume that this only read one TLV value */ - int32_t lw_time; - size_t len = ctx->reader->read_int(ctx, inbuf, insize, &lw_time); - if(len == 0) { - PRINTF("FAIL: could not read time '%*.s'\n", (int)insize, inbuf); - } else { - PRINTF("Got: time: %*.s => %" PRId32 "\n", (int)insize, inbuf, lw_time); - - time_offset = lw_time - clock_seconds(); - PRINTF("Write time...%" PRId32 " => offset = %" PRId32 "\n", - lw_time, time_offset); - } - /* return the number of bytes read */ - return len; + time_offset = time - coap_timer_seconds(); } /*---------------------------------------------------------------------------*/ -#ifdef PLATFORM_REBOOT -static struct ctimer reboot_timer; -static void -do_the_reboot(void *ptr) +static lwm2m_status_t +write_string(lwm2m_context_t *ctx, const char *text) { - PLATFORM_REBOOT(); + lwm2m_object_write_string(ctx, text, strlen(text)); + return LWM2M_STATUS_OK; } +/*---------------------------------------------------------------------------*/ static int -reboot(lwm2m_context_t *ctx, const uint8_t *arg, size_t argsize, - uint8_t *outbuf, size_t outsize) +output_multi_i16(lwm2m_context_t *ctx, const uint16_t *data, int count) { - PRINTF("Device will reboot!\n"); - ctimer_set(&reboot_timer, CLOCK_SECOND / 2, do_the_reboot, NULL); - return 0; + int i; + size_t len; + len = lwm2m_object_write_enter_ri(ctx); + for(i = 0; i < count; i++) { + len += lwm2m_object_write_int_ri(ctx, i, data[i]); + } + len += lwm2m_object_write_exit_ri(ctx); + return len; } -#endif /* PLATFORM_REBOOT */ + /*---------------------------------------------------------------------------*/ -#ifdef PLATFORM_FACTORY_DEFAULT static int -factory_reset(lwm2m_context_t *ctx, const uint8_t *arg, size_t arg_size, - uint8_t *outbuf, size_t outsize) +lwm2m_dim_callback(lwm2m_object_instance_t *object, uint16_t resource_id) { - PRINTF("Device will do factory default!\n"); - PLATFORM_FACTORY_DEFAULT(); + switch(resource_id) { + case LWM2M_DEVICE_AVAILABLE_POWER_SOURCES: + case LWM2M_DEVICE_POWER_SOURCE_VOLTAGE: + case LWM2M_DEVICE_POWER_SOURCE_CURRENT: + return sizeof(power_avail) / sizeof(uint16_t); + break; + } + /* zero means that it is no dim parameter to send?? */ return 0; } -#endif /* PLATFORM_FACTORY_DEFAULT */ /*---------------------------------------------------------------------------*/ -LWM2M_RESOURCES(device_resources, -#ifdef LWM2M_DEVICE_MANUFACTURER - LWM2M_RESOURCE_STRING(0, LWM2M_DEVICE_MANUFACTURER), -#endif /* LWM2M_DEVICE_MANUFACTURER */ -#ifdef LWM2M_DEVICE_TYPE - LWM2M_RESOURCE_STRING(17, LWM2M_DEVICE_TYPE), -#endif /* LWM2M_DEVICE_TYPE */ -#ifdef LWM2M_DEVICE_MODEL_NUMBER - LWM2M_RESOURCE_STRING(1, LWM2M_DEVICE_MODEL_NUMBER), -#endif /* LWM2M_DEVICE_MODEL_NUMBER */ -#ifdef LWM2M_DEVICE_SERIAL_NO - LWM2M_RESOURCE_STRING(2, LWM2M_DEVICE_SERIAL_NO), -#endif /* LWM2M_DEVICE_SERIAL_NO */ -#ifdef LWM2M_DEVICE_FIRMWARE_VERSION - LWM2M_RESOURCE_STRING(3, LWM2M_DEVICE_FIRMWARE_VERSION), -#endif /* LWM2M_DEVICE_FIRMWARE_VERSION */ -#ifdef PLATFORM_REBOOT - LWM2M_RESOURCE_CALLBACK(4, { NULL, NULL, reboot }), -#endif /* PLATFORM_REBOOT */ -#ifdef PLATFORM_FACTORY_DEFAULT - LWM2M_RESOURCE_CALLBACK(5, { NULL, NULL, factory_reset }), -#endif /* PLATFORM_FACTORY_DEFAULT */ - /* Current Time */ - LWM2M_RESOURCE_CALLBACK(13, { read_lwtime, set_lwtime, NULL }), - ); -LWM2M_INSTANCES(device_instances, LWM2M_INSTANCE(0, device_resources)); -LWM2M_OBJECT(device, 3, device_instances); +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, lwm2m_context_t *ctx) +{ + if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case LWM2M_DEVICE_MANUFACTURER_ID: + return write_string(ctx, LWM2M_DEVICE_MANUFACTURER); + case LWM2M_DEVICE_MODEL_NUMBER_ID: + return write_string(ctx, LWM2M_DEVICE_MODEL_NUMBER); + case LWM2M_DEVICE_SERIAL_NUMBER_ID: + return write_string(ctx, LWM2M_DEVICE_SERIAL_NUMBER); + case LWM2M_DEVICE_FIRMWARE_VERSION_ID: + return write_string(ctx, LWM2M_DEVICE_FIRMWARE_VERSION); + case LWM2M_DEVICE_TYPE_ID: + return write_string(ctx, LWM2M_DEVICE_TYPE); + case LWM2M_DEVICE_TIME_ID: + LOG_DBG("Reading time: %u\n", (unsigned int)lwm2m_device_get_time()); + lwm2m_object_write_int(ctx, lwm2m_device_get_time()); + return LWM2M_STATUS_OK; + case LWM2M_DEVICE_AVAILABLE_POWER_SOURCES: + /* Power Multi-resource case - just use array index as ID */ + output_multi_i16(ctx, power_avail, + sizeof(power_avail)/sizeof(uint16_t)); + return LWM2M_STATUS_OK; + case LWM2M_DEVICE_POWER_SOURCE_VOLTAGE: + output_multi_i16(ctx, power_voltage, + sizeof(power_voltage)/sizeof(uint16_t)); + return LWM2M_STATUS_OK; + case LWM2M_DEVICE_POWER_SOURCE_CURRENT: + output_multi_i16(ctx, power_current, + sizeof(power_current)/sizeof(uint16_t)); + return LWM2M_STATUS_OK; + default: + LOG_WARN("Not found: %u\n", ctx->resource_id); + return LWM2M_STATUS_NOT_FOUND; + } + + } else if(ctx->operation == LWM2M_OP_EXECUTE) { + if(ctx->resource_id == LWM2M_DEVICE_REBOOT_ID) { + /* Do THE REBOOT */ + LOG_INFO("REBOOT\n"); + return LWM2M_STATUS_OK; + } + + } else if(ctx->operation == LWM2M_OP_WRITE) { + if(ctx->resource_id == LWM2M_DEVICE_TIME_ID) { + int32_t lw_time; + size_t len; + len = lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, + &lw_time); + if(len == 0) { + LOG_WARN("FAIL: could not write time\n"); + return LWM2M_STATUS_WRITE_ERROR; + } else { + lwm2m_device_set_time(lw_time); + LOG_DBG("Write time %lu sec => offset = %ld\n", + (unsigned long)lw_time, (long)time_offset); + return LWM2M_STATUS_OK; + } + } + } + + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t device = { + .object_id = LWM2M_OBJECT_DEVICE_ID, + .instance_id = 0, + .resource_ids = resources, + .resource_count = sizeof(resources) / sizeof(lwm2m_resource_id_t), + .resource_dim_callback = lwm2m_dim_callback, + .callback = lwm2m_callback, +}; /*---------------------------------------------------------------------------*/ void lwm2m_device_init(void) { - /** - * Register this device and its handlers - the handlers - * automatically sends in the object to handle. - */ - PRINTF("*** Init lwm2m-device\n"); - lwm2m_engine_register_object(&device); + lwm2m_engine_add_object(&device); } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/lwm2m-device.h b/os/services/lwm2m/lwm2m-device.h index 4587822d596142b0672155ea2d881e36772503b4..d7389153c7e6e9f493ef0379122bf007580d3407 100644 --- a/os/services/lwm2m/lwm2m-device.h +++ b/os/services/lwm2m/lwm2m-device.h @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ @@ -46,6 +46,22 @@ #include "contiki.h" +#define LWM2M_DEVICE_MANUFACTURER_ID 0 +#define LWM2M_DEVICE_MODEL_NUMBER_ID 1 +#define LWM2M_DEVICE_SERIAL_NUMBER_ID 2 +#define LWM2M_DEVICE_FIRMWARE_VERSION_ID 3 +#define LWM2M_DEVICE_REBOOT_ID 4 +#define LWM2M_DEVICE_FACTORY_DEFAULT_ID 5 +#define LWM2M_DEVICE_AVAILABLE_POWER_SOURCES 6 +/* These do have multiple instances */ +#define LWM2M_DEVICE_POWER_SOURCE_VOLTAGE 7 +#define LWM2M_DEVICE_POWER_SOURCE_CURRENT 8 +#define LWM2M_DEVICE_BATTERY_LEVEL 9 + +#define LWM2M_DEVICE_ERROR_CODE 11 +#define LWM2M_DEVICE_TIME_ID 13 +#define LWM2M_DEVICE_TYPE_ID 17 + #ifndef LWM2M_DEVICE_MODEL_NUMBER #ifdef BOARD_STRING #define LWM2M_DEVICE_MODEL_NUMBER BOARD_STRING @@ -53,9 +69,14 @@ #endif /* LWM2M_DEVICE_MODEL_NUMBER */ #ifndef LWM2M_DEVICE_FIRMWARE_VERSION +#ifdef CONTIKI_VERSION_STRING #define LWM2M_DEVICE_FIRMWARE_VERSION CONTIKI_VERSION_STRING +#endif /* CONTIKI_VERSION_STRING */ #endif /* LWM2M_DEVICE_FIRMWARE_VERSION */ +int32_t lwm2m_device_get_time(void); +void lwm2m_device_set_time(int32_t time); + void lwm2m_device_init(void); #endif /* LWM2M_DEVICE_H_ */ diff --git a/os/services/lwm2m/lwm2m-engine.c b/os/services/lwm2m/lwm2m-engine.c index 1e313718fb770a74d03554e168ddec6b16c31933..1dca95a446e9e0f44468272039807562a7a84ed3 100644 --- a/os/services/lwm2m/lwm2m-engine.c +++ b/os/services/lwm2m/lwm2m-engine.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ @@ -41,29 +41,30 @@ * Niclas Finne <nfi@sics.se> */ -#include "contiki.h" #include "lwm2m-engine.h" #include "lwm2m-object.h" #include "lwm2m-device.h" #include "lwm2m-plain-text.h" #include "lwm2m-json.h" -#include "net/app-layer/coap/rest-engine.h" -#include "net/app-layer/coap/coap-constants.h" -#include "net/app-layer/coap/coap-engine.h" -#include "oma-tlv.h" -#include "oma-tlv-reader.h" -#include "oma-tlv-writer.h" -#include "net/ipv6/uip-ds6.h" +#include "coap-constants.h" +#include "coap-engine.h" +#include "lwm2m-tlv.h" +#include "lwm2m-tlv-reader.h" +#include "lwm2m-tlv-writer.h" +#include "lib/list.h" +#include "sys/cc.h" #include <stdio.h> #include <string.h> #include <inttypes.h> -#if UIP_CONF_IPV6_RPL -#include "rpl.h" -#endif /* UIP_CONF_IPV6_RPL */ +#ifndef LWM2M_ENGINE_CLIENT_ENDPOINT_NAME +#include "net/ipv6/uip-ds6.h" +#endif /* LWM2M_ENGINE_CLIENT_ENDPOINT_NAME */ -#define DEBUG DEBUG_NONE -#include "net/ipv6/uip-debug.h" +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-eng" +#define LOG_LEVEL LOG_LEVEL_LWM2M #ifndef LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX #ifdef LWM2M_DEVICE_MODEL_NUMBER @@ -73,342 +74,450 @@ #endif /* LWM2M_DEVICE_MODEL_NUMBER */ #endif /* LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX */ -#ifdef LWM2M_ENGINE_CONF_MAX_OBJECTS -#define MAX_OBJECTS LWM2M_ENGINE_CONF_MAX_OBJECTS -#else /* LWM2M_ENGINE_CONF_MAX_OBJECTS */ -#define MAX_OBJECTS 10 -#endif /* LWM2M_ENGINE_CONF_MAX_OBJECTS */ - -#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) -#define BS_REMOTE_PORT UIP_HTONS(5685) - -static const lwm2m_object_t *objects[MAX_OBJECTS]; -static char endpoint[32]; -static char rd_data[128]; /* allocate some data for the RD */ - -PROCESS(lwm2m_rd_client, "LWM2M Engine"); - -static uip_ipaddr_t server_ipaddr; -static uint16_t server_port = REMOTE_PORT; -static uip_ipaddr_t bs_server_ipaddr; -static uint16_t bs_server_port = BS_REMOTE_PORT; - -static uint8_t use_bootstrap = 0; -static uint8_t has_bootstrap_server_info = 0; -static uint8_t use_registration = 0; -static uint8_t has_registration_server_info = 0; -static uint8_t registered = 0; -static uint8_t bootstrapped = 0; /* bootstrap made... */ +#ifdef LWM2M_ENGINE_CONF_USE_RD_CLIENT +#define USE_RD_CLIENT LWM2M_ENGINE_CONF_USE_RD_CLIENT +#else +#define USE_RD_CLIENT 1 +#endif /* LWM2M_ENGINE_CONF_USE_RD_CLIENT */ + +#if USE_RD_CLIENT +#include "lwm2m-rd-client.h" +#endif + +/* MACRO for getting out resource ID from resource array ID + flags */ +#define RSC_ID(x) ((uint16_t)(x & 0xffff)) +#define RSC_READABLE(x) ((x & LWM2M_RESOURCE_READ) > 0) +#define RSC_WRITABLE(x) ((x & LWM2M_RESOURCE_WRITE) > 0) +#define RSC_UNSPECIFIED(x) ((x & LWM2M_RESOURCE_OP_MASK) == 0) + +/* invalid instance ID - ffff object ID */ +#define NO_INSTANCE 0xffffffff + +/* This is a double-buffer for generating BLOCKs in CoAP - the idea + is that typical LWM2M resources will fit 1 block unless they themselves + handle BLOCK transfer - having a double sized buffer makes it possible + to allow writing more than one block before sending the full block. + The RFC seems to indicate that all blocks execept the last one should + be full. +*/ +static uint8_t d_buf[COAP_MAX_BLOCK_SIZE * 2]; +static lwm2m_buffer_t lwm2m_buf = { + .len = 0, .size = COAP_MAX_BLOCK_SIZE * 2, .buffer = d_buf +}; +static lwm2m_object_instance_t instance_buffer; + +/* obj-id / ... */ +static uint16_t lwm2m_buf_lock[4]; +static uint64_t lwm2m_buf_lock_timeout = 0; + +static lwm2m_write_opaque_callback current_opaque_callback; +static int current_opaque_offset = 0; + +static coap_handler_status_t lwm2m_handler_callback(coap_message_t *request, + coap_message_t *response, + uint8_t *buffer, + uint16_t buffer_size, + int32_t *offset); +static lwm2m_object_instance_t * +next_object_instance(const lwm2m_context_t *context, lwm2m_object_t *object, lwm2m_object_instance_t *last); + +static struct { + uint16_t object_id; + uint16_t instance_id; + uint16_t token_len; + uint8_t token[COAP_TOKEN_LEN]; + /* in the future also a timeout */ +} created; + + +COAP_HANDLER(lwm2m_handler, lwm2m_handler_callback); +LIST(object_list); +LIST(generic_object_list); -void lwm2m_device_init(void); -void lwm2m_security_init(void); -void lwm2m_server_init(void); - -static const lwm2m_instance_t *get_first_instance_of_object(uint16_t id, lwm2m_context_t *context); -static const lwm2m_instance_t *get_instance(const lwm2m_object_t *object, lwm2m_context_t *context, int depth); -static const lwm2m_resource_t *get_resource(const lwm2m_instance_t *instance, lwm2m_context_t *context); -/*---------------------------------------------------------------------------*/ -static void -client_chunk_handler(void *response) -{ -#if (DEBUG) & DEBUG_PRINT - const uint8_t *chunk; - - int len = coap_get_payload(response, &chunk); - - PRINTF("|%.*s\n", len, (char *)chunk); -#endif /* (DEBUG) & DEBUG_PRINT */ -} /*---------------------------------------------------------------------------*/ -static int -index_of(const uint8_t *data, int offset, int len, uint8_t c) +static lwm2m_object_t * +get_object(uint16_t object_id) { - if(offset < 0) { - return offset; - } - for(; offset < len; offset++) { - if(data[offset] == c) { - return offset; + lwm2m_object_t *object; + for(object = list_head(generic_object_list); + object != NULL; + object = object->next) { + if(object->impl && object->impl->object_id == object_id) { + return object; } } - return -1; + return NULL; } /*---------------------------------------------------------------------------*/ static int -has_network_access(void) +has_non_generic_object(uint16_t object_id) { -#if UIP_CONF_IPV6_RPL - if(rpl_get_any_dag() == NULL) { - return 0; + lwm2m_object_instance_t *instance; + for(instance = list_head(object_list); + instance != NULL; + instance = instance->next) { + if(instance->object_id == object_id) { + return 1; + } } -#endif /* UIP_CONF_IPV6_RPL */ - return 1; + + return 0; } /*---------------------------------------------------------------------------*/ -void -lwm2m_engine_use_bootstrap_server(int use) +static lwm2m_object_instance_t * +get_instance(uint16_t object_id, uint16_t instance_id, lwm2m_object_t **o) { - use_bootstrap = use != 0; - if(use_bootstrap) { - process_poll(&lwm2m_rd_client); + lwm2m_object_instance_t *instance; + lwm2m_object_t *object; + + if(o) { + *o = NULL; + } + + for(instance = list_head(object_list); + instance != NULL; + instance = instance->next) { + if(instance->object_id == object_id) { + if(instance->instance_id == instance_id || + instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + return instance; + } + } } + + object = get_object(object_id); + if(object != NULL) { + if(o) { + *o = object; + } + if(instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + return object->impl->get_first(NULL); + } + return object->impl->get_by_id(instance_id, NULL); + } + + return NULL; } /*---------------------------------------------------------------------------*/ -void -lwm2m_engine_use_registration_server(int use) +static lwm2m_object_instance_t * +get_instance_by_context(const lwm2m_context_t *context, lwm2m_object_t **o) { - use_registration = use != 0; - if(use_registration) { - process_poll(&lwm2m_rd_client); + if(context->level < 2) { + return get_instance(context->object_id, LWM2M_OBJECT_INSTANCE_NONE, o); } + return get_instance(context->object_id, context->object_instance_id, o); } /*---------------------------------------------------------------------------*/ -void -lwm2m_engine_register_with_server(const uip_ipaddr_t *server, uint16_t port) +static lwm2m_status_t +call_instance(lwm2m_object_instance_t *instance, lwm2m_context_t *context) { - uip_ipaddr_copy(&server_ipaddr, server); - if(port != 0) { - server_port = port; - } else { - server_port = REMOTE_PORT; + if(context->level < 3) { + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + + if(instance == NULL) { + /* No instance */ + return LWM2M_STATUS_NOT_FOUND; } - has_registration_server_info = 1; - registered = 0; - if(use_registration) { - process_poll(&lwm2m_rd_client); + + if(instance->callback == NULL) { + return LWM2M_STATUS_ERROR; } + + return instance->callback(instance, context); } /*---------------------------------------------------------------------------*/ +/* This is intended to switch out a block2 transfer buffer + * It assumes that ctx containts the double buffer and that the outbuf is to + * be the new buffer in ctx. + */ static int -update_registration_server(void) +double_buffer_flush(lwm2m_buffer_t *ctxbuf, lwm2m_buffer_t *outbuf, int size) { - if(has_registration_server_info) { - return 1; + /* Copy the data from the double buffer in ctx to the outbuf and move data */ + /* If the buffer is less than size - we will output all and get remaining down + to zero */ + if(ctxbuf->len < size) { + size = ctxbuf->len; } - -#if UIP_CONF_IPV6_RPL - { - rpl_dag_t *dag; - - /* Use the DAG id as server address if no other has been specified */ - dag = rpl_get_any_dag(); - if(dag != NULL) { - uip_ipaddr_copy(&server_ipaddr, &dag->dag_id); - server_port = REMOTE_PORT; - return 1; - } + if(ctxbuf->len >= size && outbuf->size >= size) { + LOG_DBG("Double buffer - copying out %d bytes remaining: %d\n", + size, ctxbuf->len - size); + memcpy(outbuf->buffer, ctxbuf->buffer, size); + memcpy(ctxbuf->buffer, &ctxbuf->buffer[size], + ctxbuf->len - size); + ctxbuf->len -= size; + outbuf->len = size; + return outbuf->len; } -#endif /* UIP_CONF_IPV6_RPL */ - return 0; } /*---------------------------------------------------------------------------*/ -void -lwm2m_engine_register_with_bootstrap_server(const uip_ipaddr_t *server, - uint16_t port) +static inline const char * +get_method_as_string(coap_resource_flags_t method) { - uip_ipaddr_copy(&bs_server_ipaddr, server); - if(port != 0) { - bs_server_port = port; + if(method == METHOD_GET) { + return "GET"; + } else if(method == METHOD_POST) { + return "POST"; + } else if(method == METHOD_PUT) { + return "PUT"; + } else if(method == METHOD_DELETE) { + return "DELETE"; } else { - bs_server_port = BS_REMOTE_PORT; + return "UNKNOWN"; } - has_bootstrap_server_info = 1; - bootstrapped = 0; - registered = 0; - if(use_bootstrap) { - process_poll(&lwm2m_rd_client); +} +/*--------------------------------------------------------------------------*/ +static const char * +get_status_as_string(lwm2m_status_t status) +{ + static char buffer[8]; + switch(status) { + case LWM2M_STATUS_OK: + return "OK"; + case LWM2M_STATUS_ERROR: + return "ERROR"; + case LWM2M_STATUS_WRITE_ERROR: + return "WRITE ERROR"; + case LWM2M_STATUS_READ_ERROR: + return "READ ERROR"; + case LWM2M_STATUS_BAD_REQUEST: + return "BAD REQUEST"; + case LWM2M_STATUS_UNAUTHORIZED: + return "UNAUTHORIZED"; + case LWM2M_STATUS_FORBIDDEN: + return "FORBIDDEN"; + case LWM2M_STATUS_NOT_FOUND: + return "NOT FOUND"; + case LWM2M_STATUS_OPERATION_NOT_ALLOWED: + return "OPERATION NOT ALLOWED"; + case LWM2M_STATUS_NOT_ACCEPTABLE: + return "NOT ACCEPTABLE"; + case LWM2M_STATUS_UNSUPPORTED_CONTENT_FORMAT: + return "UNSUPPORTED CONTENT FORMAT"; + case LWM2M_STATUS_NOT_IMPLEMENTED: + return "NOT IMPLEMENTED"; + case LWM2M_STATUS_SERVICE_UNAVAILABLE: + return "SERVICE UNAVAILABLE"; + default: + snprintf(buffer, sizeof(buffer) - 1, "<%u>", status); + return buffer; } } -/*---------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------*/ static int -update_bootstrap_server(void) +parse_path(const char *path, int path_len, + uint16_t *oid, uint16_t *iid, uint16_t *rid) { - if(has_bootstrap_server_info) { - return 1; - } + int ret; + int pos; + uint16_t val; + char c = 0; -#if UIP_CONF_IPV6_RPL - { - rpl_dag_t *dag; + /* get object id */ + LOG_DBG("parse PATH: \""); + LOG_DBG_COAP_STRING(path, path_len); + LOG_DBG_("\"\n"); - /* Use the DAG id as server address if no other has been specified */ - dag = rpl_get_any_dag(); - if(dag != NULL) { - uip_ipaddr_copy(&bs_server_ipaddr, &dag->dag_id); - bs_server_port = REMOTE_PORT; - return 1; + ret = 0; + pos = 0; + do { + val = 0; + /* we should get a value first - consume all numbers */ + while(pos < path_len && (c = path[pos]) >= '0' && c <= '9') { + val = val * 10 + (c - '0'); + pos++; } - } -#endif /* UIP_CONF_IPV6_RPL */ - - return 0; + /* Slash will mote thing forward - and the end will be when pos == pl */ + if(c == '/' || pos == path_len) { + /* PRINTF("Setting %u = %u\n", ret, val); */ + if(ret == 0) *oid = val; + if(ret == 1) *iid = val; + if(ret == 2) *rid = val; + ret++; + pos++; + } else { + /* PRINTF("Error: illegal char '%c' at pos:%d\n", c, pos); */ + return -1; + } + } while(pos < path_len); + return ret; } -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(lwm2m_rd_client, ev, data) +/*--------------------------------------------------------------------------*/ +static int +lwm2m_engine_parse_context(const char *path, int path_len, + coap_message_t *request, coap_message_t *response, + uint8_t *outbuf, size_t outsize, + lwm2m_context_t *context) { - static coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */ - static struct etimer et; + int ret; + if(context == NULL || path == NULL) { + return 0; + } - PROCESS_BEGIN(); + ret = parse_path(path, path_len, &context->object_id, + &context->object_instance_id, &context->resource_id); - printf("RD Client started with endpoint '%s'\n", endpoint); + if(ret > 0) { + context->level = ret; + } - etimer_set(&et, 15 * CLOCK_SECOND); + return ret; +} - while(1) { - PROCESS_YIELD(); +/*---------------------------------------------------------------------------*/ +void lwm2m_engine_set_opaque_callback(lwm2m_context_t *ctx, lwm2m_write_opaque_callback cb) +{ + /* Here we should set the callback for the opaque that we are currently generating... */ + /* And we should in the future associate the callback with the CoAP message info - MID */ + LOG_DBG("Setting opaque handler - offset: %"PRIu32",%d\n", + ctx->offset, ctx->outbuf->len); - if(etimer_expired(&et)) { - if(!has_network_access()) { - /* Wait until for a network to join */ - } else if(use_bootstrap && bootstrapped == 0) { - if(update_bootstrap_server()) { - /* prepare request, TID is set by COAP_BLOCKING_REQUEST() */ - coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); - coap_set_header_uri_path(request, "/bs"); - coap_set_header_uri_query(request, endpoint); + current_opaque_offset = 0; + current_opaque_callback = cb; +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_engine_set_rd_data(lwm2m_buffer_t *outbuf, int block) +{ + /* remember things here - need to lock lwm2m buffer also!!! */ + static lwm2m_object_t *object; + static lwm2m_object_instance_t *instance; + int len; + /* pick size from outbuf */ + int maxsize = outbuf->size; + + if(lwm2m_buf_lock[0] != 0 && (lwm2m_buf_lock_timeout > coap_timer_uptime()) && + ((lwm2m_buf_lock[1] != 0xffff) || + (lwm2m_buf_lock[2] != 0xffff))) { + LOG_DBG("Set-RD: already exporting resource: %d/%d/%d\n", + lwm2m_buf_lock[1], lwm2m_buf_lock[2], lwm2m_buf_lock[3]); + /* fail - what should we return here? */ + return 0; + } - printf("Registering ID with bootstrap server ["); - uip_debug_ipaddr_print(&bs_server_ipaddr); - printf("]:%u as '%s'\n", uip_ntohs(bs_server_port), endpoint); + if(block == 0) { + LOG_DBG("Starting RD generation\n"); + /* start with simple object instances */ + instance = list_head(object_list); + object = NULL; + + if(instance == NULL) { + /* No simple object instances available */ + object = list_head(generic_object_list); + if(object == NULL) { + /* No objects of any kind available */ + return 0; + } + if(object->impl != NULL) { + instance = object->impl->get_first(NULL); + } + } - COAP_BLOCKING_REQUEST(&bs_server_ipaddr, bs_server_port, request, - client_chunk_handler); - bootstrapped++; - } - } else if(use_bootstrap && bootstrapped == 1) { - lwm2m_context_t context; - const lwm2m_instance_t *instance = NULL; - const lwm2m_resource_t *rsc; - const uint8_t *first; - int len; - - PRINTF("*** Bootstrap - checking for server info...\n"); - - /* get the security object */ - instance = get_first_instance_of_object(LWM2M_OBJECT_SECURITY_ID, &context); - if(instance != NULL) { - /* get the server URI */ - context.resource_id = LWM2M_SECURITY_SERVER_URI; - rsc = get_resource(instance, &context); - first = lwm2m_object_get_resource_string(rsc, &context); - len = lwm2m_object_get_resource_strlen(rsc, &context); - if(first != NULL && len > 0) { - int start, end; - uip_ipaddr_t addr; - int32_t port; - uint8_t secure = 0; - - PRINTF("**** Found security instance using: %.*s\n", len, first); - /* TODO Should verify it is a URI */ - - /* Check if secure */ - secure = strncmp((const char *)first, "coaps:", 6) == 0; - - /* Only IPv6 supported */ - start = index_of(first, 0, len, '['); - end = index_of(first, start, len, ']'); - if(start > 0 && end > start && - uiplib_ipaddrconv((const char *)&first[start], &addr)) { - if(first[end + 1] == ':' && - lwm2m_plain_text_read_int(first + end + 2, len - end - 2, &port)) { - } else if(secure) { - /** - * Secure CoAP should use a different port but for now - * the same port is used. - */ - port = COAP_DEFAULT_PORT; - } else { - port = COAP_DEFAULT_PORT; - } - PRINTF("Server address "); - PRINT6ADDR(&addr); - PRINTF(" port %" PRId32 "%s\n", port, secure ? " (secure)" : ""); - if(secure) { - printf("Secure CoAP requested but not supported - can not bootstrap\n"); - } else { - lwm2m_engine_register_with_server(&addr, - UIP_HTONS((uint16_t)port)); - bootstrapped++; - } - } else { - printf("** failed to parse URI %.*s\n", len, first); - } - } - } + lwm2m_buf_lock[0] = 1; /* lock "flag" */ + lwm2m_buf_lock[1] = 0xffff; + lwm2m_buf_lock[2] = 0xffff; + lwm2m_buf_lock[3] = 0xffff; + } else { + /* object and instance was static... */ + } - if(bootstrapped == 1) { - /* Not ready. Lets retry with the bootstrap server again */ - bootstrapped = 0; - } + lwm2m_buf_lock_timeout = coap_timer_uptime() + 1000; + + LOG_DBG("Generating RD list:"); + while(instance != NULL || object != NULL) { + int pos = lwm2m_buf.len; + if(instance != NULL) { + len = snprintf((char *) &lwm2m_buf.buffer[pos], + lwm2m_buf.size - pos, (pos > 0 || block > 0) ? ",</%d/%d>" : "</%d/%d>", + instance->object_id, instance->instance_id); + LOG_DBG_((pos > 0 || block > 0) ? ",</%d/%d>" : "</%d/%d>", + instance->object_id, instance->instance_id); + } else if(object->impl != NULL) { + len = snprintf((char *) &lwm2m_buf.buffer[pos], + lwm2m_buf.size - pos, + (pos > 0 || block > 0) ? ",</%d>" : "</%d>", + object->impl->object_id); + LOG_DBG_((pos > 0 || block > 0) ? ",</%d>" : "</%d>", + object->impl->object_id); + } else { + len = 0; + } + lwm2m_buf.len += len; + if(instance != NULL) { + instance = next_object_instance(NULL, object, instance); + } - } else if(use_registration && !registered && - update_registration_server()) { - int pos; - int len, i, j; - registered = 1; - - /* prepare request, TID is set by COAP_BLOCKING_REQUEST() */ - coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); - coap_set_header_uri_path(request, "/rd"); - coap_set_header_uri_query(request, endpoint); - - /* generate the rd data */ - pos = 0; - for(i = 0; i < MAX_OBJECTS; i++) { - if(objects[i] != NULL) { - for(j = 0; j < objects[i]->count; j++) { - if(objects[i]->instances[j].flag & LWM2M_INSTANCE_FLAG_USED) { - len = snprintf(&rd_data[pos], sizeof(rd_data) - pos, - "%s<%d/%d>", pos > 0 ? "," : "", - objects[i]->id, objects[i]->instances[j].id); - if(len > 0 && len < sizeof(rd_data) - pos) { - pos += len; - } - } - } - } - } + if(instance == NULL) { + if(object == NULL) { + /* + * No object and no instance - we are done with simple object instances. + */ + object = list_head(generic_object_list); + } else { + /* + * Object exists but not an instance - instances for this object are + * done - go to next. + */ + object = object->next; + } - coap_set_payload(request, (uint8_t *)rd_data, pos); + if(object != NULL && object->impl != NULL) { + instance = object->impl->get_first(NULL); + } - printf("Registering with ["); - uip_debug_ipaddr_print(&server_ipaddr); - printf("]:%u lwm2m endpoint '%s': '%.*s'\n", uip_ntohs(server_port), - endpoint, pos, rd_data); - COAP_BLOCKING_REQUEST(&server_ipaddr, server_port, request, - client_chunk_handler); + if(instance == NULL && object == NULL && lwm2m_buf.len <= maxsize) { + /* Data generation is done. No more messages are needed after this. */ + break; } - /* for now only register once... registered = 0; */ - etimer_set(&et, 15 * CLOCK_SECOND); + } + + if(lwm2m_buf.len >= maxsize) { + LOG_DBG_("\n"); + LOG_DBG("**** CoAP MAX BLOCK Reached!!! **** SEND\n"); + /* If the produced data is larger than a CoAP block we need to send + this now */ + double_buffer_flush(&lwm2m_buf, outbuf, maxsize); + /* there will be more - keep lock! */ + return 1; } } - PROCESS_END(); + LOG_DBG_("\n"); + double_buffer_flush(&lwm2m_buf, outbuf, maxsize); + /* unlock the buffer */ + lwm2m_buf_lock[0] = 0; + return 0; } /*---------------------------------------------------------------------------*/ void lwm2m_engine_init(void) { -#ifdef LWM2M_ENGINE_CLIENT_ENDPOINT_NAME + list_init(object_list); + list_init(generic_object_list); - snprintf(endpoint, sizeof(endpoint) - 1, - "?ep=" LWM2M_ENGINE_CLIENT_ENDPOINT_NAME); +#ifdef LWM2M_ENGINE_CLIENT_ENDPOINT_NAME + const char *endpoint = LWM2M_ENGINE_CLIENT_ENDPOINT_NAME; #else /* LWM2M_ENGINE_CLIENT_ENDPOINT_NAME */ - + static char endpoint[32]; int len, i; uint8_t state; uip_ipaddr_t *ipaddr; - char client[sizeof(endpoint)]; len = strlen(LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX); /* ensure that this fits with the hex-nums */ - if(len > sizeof(client) - 13) { - len = sizeof(client) - 13; + if(len > sizeof(endpoint) - 13) { + len = sizeof(endpoint) - 13; } - memcpy(client, LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX, len); + for(i = 0; i < len; i++) { + if(LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX[i] == ' ') { + endpoint[i] = '-'; + } else { + endpoint[i] = LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX[i]; + } + } /* pick an IP address that is PREFERRED or TENTATIVE */ ipaddr = NULL; for(i = 0; i < UIP_DS6_ADDR_NB; i++) { @@ -424,705 +533,1110 @@ lwm2m_engine_init(void) for(i = 0; i < 6; i++) { /* assume IPv6 for now */ uint8_t b = ipaddr->u8[10 + i]; - client[len++] = (b >> 4) > 9 ? 'A' - 10 + (b >> 4) : '0' + (b >> 4); - client[len++] = (b & 0xf) > 9 ? 'A' - 10 + (b & 0xf) : '0' + (b & 0xf); + endpoint[len++] = (b >> 4) > 9 ? 'A' - 10 + (b >> 4) : '0' + (b >> 4); + endpoint[len++] = (b & 0xf) > 9 ? 'A' - 10 + (b & 0xf) : '0' + (b & 0xf); } } /* a zero at end of string */ - client[len] = 0; - /* create endpoint */ - snprintf(endpoint, sizeof(endpoint) - 1, "?ep=%s", client); + endpoint[len] = 0; #endif /* LWM2M_ENGINE_CLIENT_ENDPOINT_NAME */ - rest_init_engine(); - process_start(&lwm2m_rd_client, NULL); + coap_engine_init(); + + /* Register the CoAP handler for lightweight object handling */ + coap_add_handler(&lwm2m_handler); + +#if USE_RD_CLIENT + lwm2m_rd_client_init(endpoint); +#endif } /*---------------------------------------------------------------------------*/ -void -lwm2m_engine_register_default_objects(void) +/* + * Set the writer pointer to the proper writer based on the Accept: header + * + * param[in] context LWM2M context to operate on + * param[in] accept Accept type number from CoAP headers + * + * return The content type of the response if the selected writer is used + */ +static unsigned int +lwm2m_engine_select_writer(lwm2m_context_t *context, unsigned int accept) { - lwm2m_security_init(); - lwm2m_server_init(); - lwm2m_device_init(); + switch(accept) { + case LWM2M_TLV: + case LWM2M_OLD_TLV: + context->writer = &lwm2m_tlv_writer; + break; + case LWM2M_TEXT_PLAIN: + case TEXT_PLAIN: + context->writer = &lwm2m_plain_text_writer; + break; + case LWM2M_JSON: + case LWM2M_OLD_JSON: + case APPLICATION_JSON: + context->writer = &lwm2m_json_writer; + break; + default: + LOG_WARN("Unknown Accept type %u, using LWM2M plain text\n", accept); + context->writer = &lwm2m_plain_text_writer; + /* Set the response type to plain text */ + accept = LWM2M_TEXT_PLAIN; + break; + } + context->content_type = accept; + return accept; } /*---------------------------------------------------------------------------*/ -static int -parse_next(const char **path, int *path_len, uint16_t *value) +/* + * Set the reader pointer to the proper reader based on the Content-format: header + * + * param[in] context LWM2M context to operate on + * param[in] content_format Content-type type number from CoAP headers + */ +static void +lwm2m_engine_select_reader(lwm2m_context_t *context, unsigned int content_format) { - char c; - *value = 0; - /* printf("parse_next: %p %d\n", *path, *path_len); */ - if(*path_len == 0) { - return 0; - } - while(*path_len > 0) { - c = **path; - (*path)++; - *path_len = *path_len - 1; - if(c >= '0' && c <= '9') { - *value = *value * 10 + (c - '0'); - } else if(c == '/') { - return 1; - } else { - /* error */ - return -4; - } + switch(content_format) { + case LWM2M_TLV: + case LWM2M_OLD_TLV: + context->reader = &lwm2m_tlv_reader; + break; + case LWM2M_JSON: + case LWM2M_OLD_JSON: + context->reader = &lwm2m_plain_text_reader; + break; + case LWM2M_TEXT_PLAIN: + case TEXT_PLAIN: + context->reader = &lwm2m_plain_text_reader; + break; + default: + LOG_WARN("Unknown content type %u, using LWM2M plain text\n", + content_format); + context->reader = &lwm2m_plain_text_reader; + break; } - return 1; } + /*---------------------------------------------------------------------------*/ -int -lwm2m_engine_parse_context(const lwm2m_object_t *object, - const char *path, int path_len, - lwm2m_context_t *context) +/* Lightweight object instances */ +/*---------------------------------------------------------------------------*/ +static uint32_t last_instance_id = NO_INSTANCE; +static int last_rsc_pos; + +/* Multi read will handle read of JSON / TLV or Discovery (Link Format) */ +static lwm2m_status_t +perform_multi_resource_read_op(lwm2m_object_t *object, + lwm2m_object_instance_t *instance, + lwm2m_context_t *ctx) { - int ret; - if(context == NULL || object == NULL || path == NULL) { - return 0; + int size = ctx->outbuf->size; + int len = 0; + uint8_t initialized = 0; /* used for commas, etc */ + uint8_t num_read = 0; + lwm2m_buffer_t *outbuf; + + if(instance == NULL) { + /* No existing instance */ + return LWM2M_STATUS_NOT_FOUND; } - memset(context, 0, sizeof(lwm2m_context_t)); - /* get object id */ - ret = 0; - ret += parse_next(&path, &path_len, &context->object_id); - ret += parse_next(&path, &path_len, &context->object_instance_id); - ret += parse_next(&path, &path_len, &context->resource_id); - /* Set default reader/writer */ - context->reader = &lwm2m_plain_text_reader; - context->writer = &oma_tlv_writer; + if(ctx->level < 3 && + (ctx->content_type == LWM2M_TEXT_PLAIN || + ctx->content_type == TEXT_PLAIN || + ctx->content_type == LWM2M_OLD_OPAQUE)) { + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } - return ret; -} -/*---------------------------------------------------------------------------*/ -const lwm2m_object_t * -lwm2m_engine_get_object(uint16_t id) -{ - int i; - for(i = 0; i < MAX_OBJECTS; i++) { - if(objects[i] != NULL && objects[i]->id == id) { - return objects[i]; + /* copy out the out-buffer as read will use its own - will be same for disoc when + read is fixed */ + outbuf = ctx->outbuf; + + /* Currently we only handle one incoming read request at a time - so we return + BUZY or service unavailable */ + if(lwm2m_buf_lock[0] != 0 && (lwm2m_buf_lock_timeout > coap_timer_uptime()) && + ((lwm2m_buf_lock[1] != ctx->object_id) || + (lwm2m_buf_lock[2] != ctx->object_instance_id) || + (lwm2m_buf_lock[3] != ctx->resource_id))) { + LOG_DBG("Multi-read: already exporting resource: %d/%d/%d\n", + lwm2m_buf_lock[1], lwm2m_buf_lock[2], lwm2m_buf_lock[3]); + return LWM2M_STATUS_SERVICE_UNAVAILABLE; + } + + LOG_DBG("MultiRead: %d/%d/%d lv:%d offset:%"PRIu32"\n", + ctx->object_id, ctx->object_instance_id, ctx->resource_id, + ctx->level, ctx->offset); + + /* Make use of the double buffer */ + ctx->outbuf = &lwm2m_buf; + + if(ctx->offset == 0) { + /* First GET request - need to setup all buffers and reset things here */ + last_instance_id = + ((uint32_t)instance->object_id << 16) | instance->instance_id; + last_rsc_pos = 0; + /* reset any callback */ + current_opaque_callback = NULL; + /* reset lwm2m_buf_len - so that we can use the double-size buffer */ + lwm2m_buf_lock[0] = 1; /* lock "flag" */ + lwm2m_buf_lock[1] = ctx->object_id; + lwm2m_buf_lock[2] = ctx->object_instance_id; + lwm2m_buf_lock[3] = ctx->resource_id; + lwm2m_buf.len = 0; + /* Here we should print top node */ + } else { + /* offset > 0 - assume that we are already in a disco or multi get*/ + instance = get_instance(last_instance_id >> 16, last_instance_id & 0xffff, + &object); + + /* we assume that this was initialized */ + initialized = 1; + ctx->writer_flags |= WRITER_OUTPUT_VALUE; + if(instance == NULL) { + ctx->offset = -1; + ctx->outbuf->buffer[0] = ' '; } } - return NULL; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_engine_register_object(const lwm2m_object_t *object) -{ - int i; - int found = 0; - for(i = 0; i < MAX_OBJECTS; i++) { - if(objects[i] == NULL) { - objects[i] = object; - found = 1; - break; + lwm2m_buf_lock_timeout = coap_timer_uptime() + 1000; + + while(instance != NULL) { + /* Do the discovery or read */ + if(instance->resource_ids != NULL && instance->resource_count > 0) { + /* show all the available resources (or read all) */ + while(last_rsc_pos < instance->resource_count) { + LOG_DBG("READ: 0x%"PRIx32" 0x%x 0x%x lv:%d\n", + instance->resource_ids[last_rsc_pos], + RSC_ID(instance->resource_ids[last_rsc_pos]), + ctx->resource_id, ctx->level); + + /* Check if this is a object read or if it is the correct resource */ + if(ctx->level < 3 || ctx->resource_id == RSC_ID(instance->resource_ids[last_rsc_pos])) { + /* ---------- Discovery operation ------------- */ + /* If this is a discovery all the object, instance, and resource triples should be + generted */ + if(ctx->operation == LWM2M_OP_DISCOVER) { + int dim = 0; + len = snprintf((char *) &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, + (ctx->outbuf->len == 0 && ctx->offset == 0) ? "</%d/%d/%d>":",</%d/%d/%d>", + instance->object_id, instance->instance_id, + RSC_ID(instance->resource_ids[last_rsc_pos])); + if(instance->resource_dim_callback != NULL && + (dim = instance->resource_dim_callback(instance, + RSC_ID(instance->resource_ids[last_rsc_pos]))) > 0) { + len += snprintf((char *) &ctx->outbuf->buffer[ctx->outbuf->len + len], + ctx->outbuf->size - ctx->outbuf->len - len, ";dim=%d", dim); + } + /* here we have "read" out something */ + num_read++; + ctx->outbuf->len += len; + if(len < 0 || ctx->outbuf->len >= size) { + double_buffer_flush(ctx->outbuf, outbuf, size); + + LOG_DBG("Copied lwm2m buf - remaining: %d\n", lwm2m_buf.len); + /* switch buffer */ + ctx->outbuf = outbuf; + ctx->writer_flags |= WRITER_HAS_MORE; + ctx->offset += size; + return LWM2M_STATUS_OK; + } + /* ---------- Read operation ------------- */ + } else if(ctx->operation == LWM2M_OP_READ) { + lwm2m_status_t success; + uint8_t lv; + + lv = ctx->level; + + /* Do not allow a read on a non-readable */ + if(lv == 3 && !RSC_READABLE(instance->resource_ids[last_rsc_pos])) { + lwm2m_buf_lock[0] = 0; + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + /* Set the resource ID is ctx->level < 3 */ + if(lv < 3) { + ctx->resource_id = RSC_ID(instance->resource_ids[last_rsc_pos]); + } + if(lv < 2) { + ctx->object_instance_id = instance->instance_id; + } + + if(RSC_READABLE(instance->resource_ids[last_rsc_pos])) { + ctx->level = 3; + if(!initialized) { + /* Now we need to initialize the object writing for this new object */ + len = ctx->writer->init_write(ctx); + ctx->outbuf->len += len; + LOG_DBG("INIT WRITE len:%d size:%"PRIu16"\n", len, ctx->outbuf->size); + initialized = 1; + } + + if(current_opaque_callback == NULL) { + LOG_DBG("Doing the callback to the resource %d\n", ctx->outbuf->len); + /* No special opaque callback to handle - use regular callback */ + success = instance->callback(instance, ctx); + LOG_DBG("After the callback to the resource %d: %s\n", + ctx->outbuf->len, get_status_as_string(success)); + + if(success != LWM2M_STATUS_OK) { + /* What to do here? */ + LOG_DBG("Callback failed: %s\n", get_status_as_string(success)); + if(lv < 3) { + if(success == LWM2M_STATUS_NOT_FOUND) { + /* ok with a not found during a multi read - what more + is ok? */ + } else { + lwm2m_buf_lock[0] = 0; + return success; + } + } else { + lwm2m_buf_lock[0] = 0; + return success; + } + } + } + if(current_opaque_callback != NULL) { + uint32_t old_offset = ctx->offset; + int num_write = COAP_MAX_BLOCK_SIZE - ctx->outbuf->len; + /* Check if the callback did set a opaque callback function - then + we should produce data via that callback until the opaque has fully + been handled */ + ctx->offset = current_opaque_offset; + /* LOG_DBG("Calling the opaque handler %x\n", ctx->writer_flags); */ + success = current_opaque_callback(instance, ctx, num_write); + if((ctx->writer_flags & WRITER_HAS_MORE) == 0) { + /* This opaque stream is now done! */ + /* LOG_DBG("Setting opaque callback to null - it is done!\n"); */ + current_opaque_callback = NULL; + } else if(ctx->outbuf->len < COAP_MAX_BLOCK_SIZE) { + lwm2m_buf_lock[0] = 0; + return LWM2M_STATUS_ERROR; + } + current_opaque_offset += num_write; + ctx->offset = old_offset; + /* LOG_DBG("Setting back offset to: %d\n", ctx->offset); */ + } + + /* here we have "read" out something */ + num_read++; + /* We will need to handle no-success and other things */ + LOG_DBG("Called %u/%u/%u outlen:%u %s\n", + ctx->object_id, ctx->object_instance_id, ctx->resource_id, + ctx->outbuf->len, get_status_as_string(success)); + + /* we need to handle full buffer, etc here also! */ + ctx->level = lv; + } else { + LOG_DBG("Resource %u not readable\n", + RSC_ID(instance->resource_ids[last_rsc_pos])); + } + } + } + if(current_opaque_callback == NULL) { + /* This resource is now done - (only when the opaque is also done) */ + last_rsc_pos++; + } else { + LOG_DBG("Opaque is set - continue with that.\n"); + } + + if(ctx->outbuf->len >= COAP_MAX_BLOCK_SIZE) { + LOG_DBG("**** CoAP MAX BLOCK Reached!!! **** SEND\n"); + /* If the produced data is larger than a CoAP block we need to send + this now */ + if(ctx->outbuf->len < 2 * COAP_MAX_BLOCK_SIZE) { + /* We assume that size is equal to COAP_MAX_BLOCK_SIZE here */ + double_buffer_flush(ctx->outbuf, outbuf, size); + + LOG_DBG("Copied lwm2m buf - remaining: %d\n", lwm2m_buf.len); + /* switch buffer */ + ctx->outbuf = outbuf; + ctx->writer_flags |= WRITER_HAS_MORE; + ctx->offset += size; + /* OK - everything went well... but we have more. - keep the lock here! */ + return LWM2M_STATUS_OK; + } else { + LOG_WARN("*** ERROR Overflow?\n"); + return LWM2M_STATUS_ERROR; + } + } + } + } + instance = next_object_instance(ctx, object, instance); + if(instance != NULL) { + last_instance_id = + ((uint32_t)instance->object_id << 16) | instance->instance_id; + } else { + last_instance_id = NO_INSTANCE; + } + if(ctx->operation == LWM2M_OP_READ) { + LOG_DBG("END Writer %d ->", ctx->outbuf->len); + len = ctx->writer->end_write(ctx); + ctx->outbuf->len += len; + LOG_DBG("%d\n", ctx->outbuf->len); } + + initialized = 0; + last_rsc_pos = 0; } - rest_activate_resource(lwm2m_object_get_coap_resource(object), - (char *)object->path); - return found; + + /* did not read anything even if we should have - on single item */ + if(num_read == 0 && ctx->level == 3) { + lwm2m_buf_lock[0] = 0; + return LWM2M_STATUS_NOT_FOUND; + } + + /* seems like we are done! - flush buffer */ + len = double_buffer_flush(ctx->outbuf, outbuf, size); + ctx->outbuf = outbuf; + ctx->offset += len; + + /* If there is still data in the double-buffer - indicate that so that we get another + callback */ + if(lwm2m_buf.len > 0) { + ctx->writer_flags |= WRITER_HAS_MORE; + } else { + /* OK - everything went well we are done, unlock and return */ + lwm2m_buf_lock[0] = 0; + } + + LOG_DBG("At END: Copied lwm2m buf %d\n", len); + + return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ -static const lwm2m_instance_t * -get_first_instance_of_object(uint16_t id, lwm2m_context_t *context) +static lwm2m_object_instance_t * +create_instance(lwm2m_context_t *context, lwm2m_object_t *object) { - const lwm2m_object_t *object; - int i; - - object = lwm2m_engine_get_object(id); - if(object == NULL) { - /* No object with the specified id found */ + lwm2m_object_instance_t *instance; + if(object == NULL || object->impl == NULL || + object->impl->create_instance == NULL) { return NULL; } - /* Initialize the context */ - memset(context, 0, sizeof(lwm2m_context_t)); - context->object_id = id; - - for(i = 0; i < object->count; i++) { - if(object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) { - context->object_instance_id = object->instances[i].id; - context->object_instance_index = i; - return &object->instances[i]; - } + /* NOTE: context->object_instance_id needs to be set before calling */ + instance = object->impl->create_instance(context->object_instance_id, NULL); + if(instance != NULL) { + LOG_DBG("Created instance: %u/%u\n", context->object_id, context->object_instance_id); + coap_set_status_code(context->response, CREATED_2_01); +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif } - return NULL; + return instance; } /*---------------------------------------------------------------------------*/ -static const lwm2m_instance_t * -get_instance(const lwm2m_object_t *object, lwm2m_context_t *context, int depth) +#define MODE_NONE 0 +#define MODE_INSTANCE 1 +#define MODE_VALUE 2 +#define MODE_READY 3 + +static lwm2m_object_instance_t * +get_or_create_instance(lwm2m_context_t *ctx, lwm2m_object_t *object, + uint16_t *c) { - int i; - if(depth > 1) { - PRINTF("lwm2m: searching for instance %u\n", context->object_instance_id); - for(i = 0; i < object->count; i++) { - PRINTF(" Instance %d -> %u (used: %d)\n", i, object->instances[i].id, - (object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) != 0); - if(object->instances[i].id == context->object_instance_id && - object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) { - context->object_instance_index = i; - return &object->instances[i]; + lwm2m_object_instance_t *instance; + + instance = get_instance_by_context(ctx, NULL); + LOG_DBG("Instance: %u/%u/%u = %p\n", ctx->object_id, + ctx->object_instance_id, ctx->resource_id, instance); + /* by default we assume that the instance is not created... so we set flag to zero */ + if(c != NULL) { + *c = LWM2M_OBJECT_INSTANCE_NONE; + } + if(instance == NULL) { + instance = create_instance(ctx, object); + if(instance != NULL) { + if(c != NULL) { + *c = instance->instance_id; } + created.instance_id = instance->instance_id; + created.object_id = instance->object_id; + created.token_len = MIN(COAP_TOKEN_LEN, ctx->request->token_len); + memcpy(&created.token, ctx->request->token, created.token_len); } } - return NULL; + return instance; } /*---------------------------------------------------------------------------*/ -static const lwm2m_resource_t * -get_resource(const lwm2m_instance_t *instance, lwm2m_context_t *context) +static int +check_write(lwm2m_context_t *ctx, lwm2m_object_instance_t *instance, int rid) { int i; - if(instance != NULL) { - PRINTF("lwm2m: searching for resource %u\n", context->resource_id); - for(i = 0; i < instance->count; i++) { - PRINTF(" Resource %d -> %u\n", i, instance->resources[i].id); - if(instance->resources[i].id == context->resource_id) { - context->resource_index = i; - return &instance->resources[i]; + if(instance->resource_ids != NULL && instance->resource_count > 0) { + int count = instance->resource_count; + for(i = 0; i < count; i++) { + if(RSC_ID(instance->resource_ids[i]) == rid) { + if(RSC_WRITABLE(instance->resource_ids[i])) { + /* yes - writable */ + return 1; + } + if(RSC_UNSPECIFIED(instance->resource_ids[i]) && + created.instance_id == instance->instance_id && + created.object_id == instance->object_id && + created.token_len == ctx->request->token_len && + memcmp(&created.token, ctx->request->token, + created.token_len) == 0) { + /* yes - writeable at create - never otherwise - sec / srv */ + return 1; + } + break; } } } - return NULL; + /* Resource did not exist... - Ignore to avoid problems. */ + if(created.instance_id == instance->instance_id && + created.object_id == instance->object_id && + created.token_len == ctx->request->token_len && + memcmp(&created.token, ctx->request->token, + created.token_len) == 0) { + LOG_DBG("Ignoring resource %u/%u/%d in newly created instance\n", + created.object_id, created.instance_id, rid); + return 1; + } + return 0; } /*---------------------------------------------------------------------------*/ -/** - * @brief Write a list of object instances as a CoRE Link-format list - */ -static int -write_object_instances_link(const lwm2m_object_t *object, - char *buffer, size_t size) +static lwm2m_status_t +process_tlv_write(lwm2m_context_t *ctx, lwm2m_object_t *object, + int rid, uint8_t *data, int len) { - const lwm2m_instance_t *instance; - int len, rdlen, i; - - PRINTF("</%d>", object->id); - rdlen = snprintf(buffer, size, "</%d>", - object->id); - if(rdlen < 0 || rdlen >= size) { - return -1; - } - - for(i = 0; i < object->count; i++) { - if((object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) == 0) { - continue; - } - instance = &object->instances[i]; - PRINTF(",</%d/%d>", object->id, instance->id); - - len = snprintf(&buffer[rdlen], size - rdlen, - ",<%d/%d>", object->id, instance->id); - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; + lwm2m_object_instance_t *instance; + uint16_t created = LWM2M_OBJECT_INSTANCE_NONE; + ctx->inbuf->buffer = data; + ctx->inbuf->pos = 0; + ctx->inbuf->size = len; + ctx->level = 3; + ctx->resource_id = rid; + LOG_DBG(" Doing callback to %u/%u/%u\n", ctx->object_id, + ctx->object_instance_id, ctx->resource_id); + instance = get_or_create_instance(ctx, object, &created); + if(instance != NULL && instance->callback != NULL) { + if(check_write(ctx, instance, rid)) { + return instance->callback(instance, ctx); + } else { + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; } } - return rdlen; + return LWM2M_STATUS_ERROR; } /*---------------------------------------------------------------------------*/ -static int -write_rd_link_data(const lwm2m_object_t *object, - const lwm2m_instance_t *instance, - char *buffer, size_t size) +static int last_tlv_id = 0; + +static lwm2m_status_t +perform_multi_resource_write_op(lwm2m_object_t *object, + lwm2m_object_instance_t *instance, + lwm2m_context_t *ctx, int format) { - const lwm2m_resource_t *resource; - int len, rdlen, i; - - PRINTF("<%d/%d>", object->id, instance->id); - rdlen = snprintf(buffer, size, "<%d/%d>", - object->id, instance->id); - if(rdlen < 0 || rdlen >= size) { - return -1; - } + /* Only for JSON and TLV formats */ + uint16_t oid = 0, iid = 0, rid = 0; + uint8_t olv = 0; + uint8_t mode = 0; + uint8_t *inbuf; + int inpos; + size_t insize; + int i; + uint16_t created = LWM2M_OBJECT_INSTANCE_NONE; - for(i = 0; i < instance->count; i++) { - resource = &instance->resources[i]; - PRINTF(",<%d/%d/%d>", object->id, instance->id, resource->id); + olv = ctx->level; + inbuf = ctx->inbuf->buffer; + inpos = ctx->inbuf->pos; + insize = ctx->inbuf->size; - len = snprintf(&buffer[rdlen], size - rdlen, - ",<%d/%d/%d>", object->id, instance->id, resource->id); - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; + if(format == LWM2M_JSON || format == LWM2M_OLD_JSON) { + struct json_data json; + + while(lwm2m_json_next_token(ctx, &json)) { + LOG_DBG("JSON: '"); + for(i = 0; i < json.name_len; i++) { + LOG_DBG_("%c", json.name[i]); + } + LOG_DBG_("':'"); + for(i = 0; i < json.value_len; i++) { + LOG_DBG_("%c", json.value[i]); + } + LOG_DBG_("'\n"); + + if(json.name[0] == 'n') { + i = parse_path((const char *) json.value, json.value_len, &oid, &iid, &rid); + if(i > 0) { + if(ctx->level == 1) { + ctx->level = 3; + ctx->object_instance_id = oid; + ctx->resource_id = iid; + + instance = get_or_create_instance(ctx, object, &created); + } + if(instance != NULL && instance->callback != NULL) { + mode |= MODE_INSTANCE; + } else { + /* Failure... */ + return LWM2M_STATUS_ERROR; + } + } + } else { + /* HACK - assume value node - can it be anything else? */ + mode |= MODE_VALUE; + /* update values */ + inbuf = ctx->inbuf->buffer; + inpos = ctx->inbuf->pos; + + ctx->inbuf->buffer = json.value; + ctx->inbuf->pos = 0; + ctx->inbuf->size = json.value_len; + } + + if(mode == MODE_READY) { + /* allow write if just created - otherwise not */ + if(!check_write(ctx, instance, ctx->resource_id)) { + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + if(instance->callback(instance, ctx) != LWM2M_STATUS_OK) { + /* TODO what to do here */ + } + mode = MODE_NONE; + ctx->inbuf->buffer = inbuf; + ctx->inbuf->pos = inpos; + ctx->inbuf->size = insize; + ctx->level = olv; + } + } + } else if(format == LWM2M_TLV || format == LWM2M_OLD_TLV) { + size_t len; + lwm2m_tlv_t tlv; + int tlvpos = 0; + lwm2m_status_t status; + + /* For handling blockwise (BLOCK1) write */ + uint32_t num; + uint8_t more; + uint16_t size; + uint32_t offset; + + /* NOTE: this assumes that a BLOCK1 non-first block is not a part of a + small TLV but rather a large opaque - this needs to be fixed in the + future */ + + if(coap_get_header_block1(ctx->request, &num, &more, &size, &offset)) { + LOG_DBG("CoAP BLOCK1: %"PRIu32"/%d/%d offset:%"PRIu32 + " LWM2M CTX->offset=%"PRIu32"\n", + num, more, size, offset, ctx->offset); + LOG_DBG("Last TLV ID:%d final:%d\n", last_tlv_id, + lwm2m_object_is_final_incoming(ctx)); + if(offset > 0) { + status = process_tlv_write(ctx, object, last_tlv_id, + inbuf, size); + return status; + } } + + while(tlvpos < insize) { + len = lwm2m_tlv_read(&tlv, &inbuf[tlvpos], insize - tlvpos); + LOG_DBG("Got TLV format First is: type:%d id:%d len:%d (p:%d len:%d/%d)\n", + tlv.type, tlv.id, (int) tlv.length, + (int) tlvpos, (int) len, (int) insize); + if(tlv.type == LWM2M_TLV_TYPE_OBJECT_INSTANCE) { + lwm2m_tlv_t tlv2; + int len2; + int pos = 0; + ctx->object_instance_id = tlv.id; + if(tlv.length == 0) { + /* Create only - no data */ + if((instance = create_instance(ctx, object)) == NULL) { + return LWM2M_STATUS_ERROR; + } + } + while(pos < tlv.length && (len2 = lwm2m_tlv_read(&tlv2, &tlv.value[pos], + tlv.length - pos))) { + LOG_DBG(" TLV type:%d id:%d len:%d (len:%d/%d)\n", + tlv2.type, tlv2.id, (int)tlv2.length, + (int)len2, (int)insize); + if(tlv2.type == LWM2M_TLV_TYPE_RESOURCE) { + last_tlv_id = tlv2.id; + status = process_tlv_write(ctx, object, tlv2.id, + (uint8_t *)&tlv.value[pos], len2); + if(status != LWM2M_STATUS_OK) { + return status; + } + } + pos += len2; + } + } else if(tlv.type == LWM2M_TLV_TYPE_RESOURCE) { + status = process_tlv_write(ctx, object, tlv.id, &inbuf[tlvpos], len); + if(status != LWM2M_STATUS_OK) { + return status; + } + coap_set_status_code(ctx->response, CHANGED_2_04); + } + tlvpos += len; + } + } else if(format == LWM2M_TEXT_PLAIN || + format == TEXT_PLAIN || + format == LWM2M_OLD_OPAQUE) { + return call_instance(instance, ctx); + + } else { + /* Unsupported format */ + return LWM2M_STATUS_UNSUPPORTED_CONTENT_FORMAT; } - return rdlen; + + /* Here we have a success! */ + return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ -static int -write_rd_json_data(const lwm2m_context_t *context, - const lwm2m_object_t *object, - const lwm2m_instance_t *instance, - char *buffer, size_t size) +lwm2m_object_instance_t * +lwm2m_engine_get_instance_buffer(void) +{ + return &instance_buffer; +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_engine_has_instance(uint16_t object_id, uint16_t instance_id) { - const lwm2m_resource_t *resource; - const char *s = ""; - int len, rdlen, i; - - PRINTF("{\"e\":["); - rdlen = snprintf(buffer, size, "{\"e\":["); - if(rdlen < 0 || rdlen >= size) { - return -1; + return get_instance(object_id, instance_id, NULL) != NULL; +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_engine_add_object(lwm2m_object_instance_t *object) +{ + lwm2m_object_instance_t *instance; + uint16_t min_id = 0xffff; + uint16_t max_id = 0; + int found = 0; + + if(object == NULL || object->callback == NULL) { + /* Insufficient object configuration */ + LOG_DBG("failed to register NULL object\n"); + return 0; + } + if(get_object(object->object_id) != NULL) { + /* A generic object with this id has already been registered */ + LOG_DBG("object with id %u already registered\n", object->object_id); + return 0; } - for(i = 0, len = 0; i < instance->count; i++) { - resource = &instance->resources[i]; - len = 0; - if(lwm2m_object_is_resource_string(resource)) { - const uint8_t *value; - uint16_t slen; - value = lwm2m_object_get_resource_string(resource, context); - slen = lwm2m_object_get_resource_strlen(resource, context); - if(value != NULL) { - PRINTF("%s{\"n\":\"%u\",\"sv\":\"%.*s\"}", s, - resource->id, slen, value); - len = snprintf(&buffer[rdlen], size - rdlen, - "%s{\"n\":\"%u\",\"sv\":\"%.*s\"}", s, - resource->id, slen, value); + for(instance = list_head(object_list); + instance != NULL; + instance = instance->next) { + if(object->object_id == instance->object_id) { + if(object->instance_id == instance->instance_id) { + LOG_DBG("object with id %u/%u already registered\n", + instance->object_id, instance->instance_id); + return 0; } - } else if(lwm2m_object_is_resource_int(resource)) { - int32_t value; - if(lwm2m_object_get_resource_int(resource, context, &value)) { - PRINTF("%s{\"n\":\"%u\",\"v\":%" PRId32 "}", s, - resource->id, value); - len = snprintf(&buffer[rdlen], size - rdlen, - "%s{\"n\":\"%u\",\"v\":%" PRId32 "}", s, - resource->id, value); - } - } else if(lwm2m_object_is_resource_floatfix(resource)) { - int32_t value; - if(lwm2m_object_get_resource_floatfix(resource, context, &value)) { - PRINTF("%s{\"n\":\"%u\",\"v\":%" PRId32 "}", s, resource->id, - value / LWM2M_FLOAT32_FRAC); - len = snprintf(&buffer[rdlen], size - rdlen, - "%s{\"n\":\"%u\",\"v\":", s, resource->id); - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; - } - - len = lwm2m_plain_text_write_float32fix((uint8_t *)&buffer[rdlen], - size - rdlen, - value, LWM2M_FLOAT32_BITS); - if(len == 0) { - return -1; - } - rdlen += len; - if(rdlen < size) { - buffer[rdlen] = '}'; - } - len = 1; + found++; + if(instance->instance_id > max_id) { + max_id = instance->instance_id; } - } else if(lwm2m_object_is_resource_boolean(resource)) { - int value; - if(lwm2m_object_get_resource_boolean(resource, context, &value)) { - PRINTF("%s{\"n\":\"%u\",\"bv\":%s}", s, resource->id, - value ? "true" : "false"); - len = snprintf(&buffer[rdlen], size - rdlen, - "%s{\"n\":\"%u\",\"bv\":%s}", s, resource->id, - value ? "true" : "false"); + if(instance->instance_id < min_id) { + min_id = instance->instance_id; } } - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; - } - if(len > 0) { - s = ","; + } + + if(object->instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + /* No instance id has been assigned yet */ + if(found == 0) { + /* First object with this id */ + object->instance_id = 0; + } else if(min_id > 0) { + object->instance_id = min_id - 1; + } else { + object->instance_id = max_id + 1; } } - PRINTF("]}\n"); - len = snprintf(&buffer[rdlen], size - rdlen, "]}"); - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; + list_add(object_list, object); +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif + return 1; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_engine_remove_object(lwm2m_object_instance_t *object) +{ + list_remove(object_list, object); +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_engine_add_generic_object(lwm2m_object_t *object) +{ + if(object == NULL || object->impl == NULL + || object->impl->get_first == NULL + || object->impl->get_next == NULL + || object->impl->get_by_id == NULL) { + LOG_WARN("failed to register NULL object\n"); + return 0; + } + if(get_object(object->impl->object_id) != NULL) { + /* A generic object with this id has already been registered */ + LOG_WARN("object with id %u already registered\n", + object->impl->object_id); + return 0; } + if(has_non_generic_object(object->impl->object_id)) { + /* An object with this id has already been registered */ + LOG_WARN("object with id %u already registered\n", + object->impl->object_id); + return 0; + } + list_add(generic_object_list, object); + +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif - return rdlen; + return 1; } /*---------------------------------------------------------------------------*/ -/** - * @brief Set the writer pointer to the proper writer based on the Accept: header - * - * @param[in] context LWM2M context to operate on - * @param[in] accept Accept type number from CoAP headers - * - * @return The content type of the response if the selected writer is used - */ -static unsigned int -lwm2m_engine_select_writer(lwm2m_context_t *context, unsigned int accept) +void +lwm2m_engine_remove_generic_object(lwm2m_object_t *object) { - switch(accept) { - case LWM2M_TLV: - context->writer = &oma_tlv_writer; - break; - case LWM2M_TEXT_PLAIN: - case TEXT_PLAIN: - context->writer = &lwm2m_plain_text_writer; - break; - case LWM2M_JSON: - case APPLICATION_JSON: - context->writer = &lwm2m_json_writer; - break; - default: - PRINTF("Unknown Accept type %u, using LWM2M plain text\n", accept); - context->writer = &lwm2m_plain_text_writer; - /* Set the response type to plain text */ - accept = LWM2M_TEXT_PLAIN; - break; - } - return accept; + list_remove(generic_object_list, object); +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif } /*---------------------------------------------------------------------------*/ -/** - * @brief Set the reader pointer to the proper reader based on the Content-format: header - * - * @param[in] context LWM2M context to operate on - * @param[in] content_format Content-type type number from CoAP headers - */ -static void -lwm2m_engine_select_reader(lwm2m_context_t *context, unsigned int content_format) +static lwm2m_object_instance_t * +next_object_instance(const lwm2m_context_t *context, lwm2m_object_t *object, + lwm2m_object_instance_t *last) { - switch(content_format) { - case LWM2M_TLV: - context->reader = &oma_tlv_reader; - break; - case LWM2M_TEXT_PLAIN: - case TEXT_PLAIN: - context->reader = &lwm2m_plain_text_reader; - break; - default: - PRINTF("Unknown content type %u, using LWM2M plain text\n", accept); - context->reader = &lwm2m_plain_text_reader; - break; + if(context != NULL && context->level >= 2) { + /* Only single instance */ + return NULL; + } + + /* There has to be a last to get a next */ + if(last == NULL) { + return NULL; + } + + if(object == NULL) { + for(last = last->next; last != NULL; last = last->next) { + /* if no context is given - this will just give the next object */ + if(context == NULL || last->object_id == context->object_id) { + return last; + } + } + return NULL; } + return object->impl->get_next(last, NULL); } /*---------------------------------------------------------------------------*/ -void -lwm2m_engine_handler(const lwm2m_object_t *object, - void *request, void *response, - uint8_t *buffer, uint16_t preferred_size, - int32_t *offset) +static coap_handler_status_t +lwm2m_handler_callback(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t buffer_size, int32_t *offset) { - int len; const char *url; + int url_len; unsigned int format; unsigned int accept; - unsigned int content_type; int depth; lwm2m_context_t context; - rest_resource_flags_t method; - const lwm2m_instance_t *instance; -#if (DEBUG) & DEBUG_PRINT - const char *method_str; -#endif /* (DEBUG) & DEBUG_PRINT */ - - method = REST.get_method_type(request); - - len = REST.get_url(request, &url); - if(!REST.get_header_content_type(request, &format)) { - PRINTF("No format given. Assume text plain...\n"); - format = LWM2M_TEXT_PLAIN; - } else if(format == TEXT_PLAIN) { - /* CoAP content format text plain - assume LWM2M text plain */ - format = LWM2M_TEXT_PLAIN; + lwm2m_object_t *object; + lwm2m_object_instance_t *instance; + uint32_t bnum; + uint8_t bmore; + uint16_t bsize; + uint32_t boffset; + lwm2m_status_t success; + lwm2m_buffer_t inbuf; + lwm2m_buffer_t outbuf; + + /* Initialize the context */ + memset(&context, 0, sizeof(context)); + memset(&outbuf, 0, sizeof(outbuf)); + memset(&inbuf, 0, sizeof(inbuf)); + + context.outbuf = &outbuf; + context.inbuf = &inbuf; + + /* Set CoAP request/response for now */ + context.request = request; + context.response = response; + + /* Set out buffer */ + context.outbuf->buffer = buffer; + context.outbuf->size = buffer_size; + + /* Set input buffer */ + if(offset != NULL) { + context.offset = *offset; } - if(!REST.get_header_accept(request, &accept)) { - PRINTF("No Accept header, using same as Content-format...\n"); - accept = format; + context.inbuf->size = coap_get_payload(request, (const uint8_t **)&context.inbuf->buffer); + context.inbuf->pos = 0; + + /* Maybe this should be part of CoAP itself - this seems not to be working + with the leshan server */ +#define LWM2M_CONF_ENTITY_TOO_LARGE_BLOCK1 0 +#if LWM2M_CONF_ENTITY_TOO_LARGE_BLOCK1 + if(coap_is_option(request, COAP_OPTION_BLOCK1)) { + uint16_t bsize; + coap_get_header_block1(request, NULL, NULL, &bsize, NULL); + + LOG_DBG("Block1 size:%d\n", bsize); + if(bsize > COAP_MAX_BLOCK_SIZE) { + LOG_WARN("Entity too large: %u...\n", bsize); + coap_set_status_code(response, REQUEST_ENTITY_TOO_LARGE_4_13); + coap_set_header_size1(response, COAP_MAX_BLOCK_SIZE); + return COAP_HANDLER_STATUS_PROCESSED; + } } +#endif - depth = lwm2m_engine_parse_context(object, url, len, &context); - PRINTF("Context: %u/%u/%u found: %d\n", context.object_id, - context.object_instance_id, context.resource_id, depth); + /* Set default reader/writer */ + context.reader = &lwm2m_plain_text_reader; + context.writer = &lwm2m_tlv_writer; - /* Select reader and writer based on provided Content type and Accept headers */ - lwm2m_engine_select_reader(&context, format); - content_type = lwm2m_engine_select_writer(&context, accept); -#if (DEBUG) & DEBUG_PRINT - /* for debugging */ - if(method == METHOD_GET) { - method_str = "GET"; - } else if(method == METHOD_POST) { - method_str = "POST"; - } else if(method == METHOD_PUT) { - method_str = "PUT"; - } else if(method == METHOD_DELETE) { - method_str = "DELETE"; - } else { - method_str = "UNKNOWN"; + url_len = coap_get_header_uri_path(request, &url); + + if(url_len == 2 && strncmp("bs", url, 2) == 0) { + LOG_INFO("BOOTSTRAPPED!!!\n"); + coap_set_status_code(response, CHANGED_2_04); + return COAP_HANDLER_STATUS_PROCESSED; } - PRINTF("%s Called Path:%.*s Format:%d ID:%d bsize:%u\n", method_str, len, - url, format, object->id, preferred_size); - if(format == LWM2M_TEXT_PLAIN) { - /* a string */ - const uint8_t *data; - int plen = REST.get_request_payload(request, &data); - if(plen > 0) { - PRINTF("Data: '%.*s'\n", plen, (char *)data); + + depth = lwm2m_engine_parse_context(url, url_len, request, response, + buffer, buffer_size, &context); + if(depth < 0) { + /* Not a LWM2M context */ + return COAP_HANDLER_STATUS_CONTINUE; + } + + LOG_DBG("%s URL:'", get_method_as_string(coap_get_method_type(request))); + LOG_DBG_COAP_STRING(url, url_len); + LOG_DBG_("' CTX:%u/%u/%u dp:%u bs:%d\n", context.object_id, context.object_instance_id, + context.resource_id, depth, buffer_size); + /* Get format and accept */ + if(!coap_get_header_content_format(request, &format)) { + LOG_DBG("No format given. Assume text plain...\n"); + format = TEXT_PLAIN; + } else if(format == LWM2M_TEXT_PLAIN) { + /* CoAP content format text plain - assume LWM2M text plain */ + format = TEXT_PLAIN; + } + if(!coap_get_header_accept(request, &accept)) { + if(format == TEXT_PLAIN && depth < 3) { + LOG_DBG("No Accept header, assume JSON\n"); + accept = LWM2M_JSON; + } else { + LOG_DBG("No Accept header, using same as content-format: %d\n", format); + accept = format; + } + } + + /* + * 1 => Object only + * 2 => Object and Instance + * 3 => Object and Instance and Resource + */ + if(depth < 1) { + /* No possible object id found in URL - ignore request unless delete all */ + if(coap_get_method_type(request) == METHOD_DELETE) { + LOG_DBG("This is a delete all - for bootstrap...\n"); + context.operation = LWM2M_OP_DELETE; + coap_set_status_code(response, DELETED_2_02); + + /* Delete all dynamic objects that can be deleted */ + for(object = list_head(generic_object_list); + object != NULL; + object = object->next) { + if(object->impl != NULL && object->impl->delete_instance != NULL) { + object->impl->delete_instance(LWM2M_OBJECT_INSTANCE_NONE, NULL); + } + } +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif + return COAP_HANDLER_STATUS_PROCESSED; } + return COAP_HANDLER_STATUS_CONTINUE; } -#endif /* (DEBUG) & DEBUG_PRINT */ - instance = get_instance(object, &context, depth); + instance = get_instance_by_context(&context, &object); - /* from POST */ - if(depth > 1 && instance == NULL) { - if(method != METHOD_PUT && method != METHOD_POST) { - PRINTF("Error - do not have instance %d\n", context.object_instance_id); - REST.set_response_status(response, NOT_FOUND_4_04); - return; + /* + * Check if we found either instance or object. Instance means we found an + * existing instance and generic objects means we might create an instance. + */ + if(instance == NULL && object == NULL) { + /* No matching object/instance found - ignore request */ + return COAP_HANDLER_STATUS_CONTINUE; + } + + LOG_INFO("Context: %u/%u/%u found: %d\n", + context.object_id, context.object_instance_id, + context.resource_id, depth); + + /* + * Select reader and writer based on provided Content type and + * Accept headers. + */ + lwm2m_engine_select_reader(&context, format); + lwm2m_engine_select_writer(&context, accept); + + switch(coap_get_method_type(request)) { + case METHOD_PUT: + /* can also be write atts */ + context.operation = LWM2M_OP_WRITE; + coap_set_status_code(response, CHANGED_2_04); + break; + case METHOD_POST: + if(context.level < 2) { + /* write to a instance */ + context.operation = LWM2M_OP_WRITE; + coap_set_status_code(response, CHANGED_2_04); + } else if(context.level == 3) { + context.operation = LWM2M_OP_EXECUTE; + coap_set_status_code(response, CHANGED_2_04); + } + break; + case METHOD_GET: + if(accept == APPLICATION_LINK_FORMAT) { + context.operation = LWM2M_OP_DISCOVER; } else { + context.operation = LWM2M_OP_READ; + } + coap_set_status_code(response, CONTENT_2_05); + break; + case METHOD_DELETE: + context.operation = LWM2M_OP_DELETE; + coap_set_status_code(response, DELETED_2_02); + break; + default: + break; + } + + if(LOG_DBG_ENABLED) { + /* for debugging */ + LOG_DBG("["); + LOG_DBG_COAP_STRING(url, url_len); + LOG_DBG_("] %s Format:%d ID:%d bsize:%u offset:%"PRId32"\n", + get_method_as_string(coap_get_method_type(request)), + format, context.object_id, buffer_size, + offset != NULL ? *offset : 0); + if(format == TEXT_PLAIN) { + /* a string */ const uint8_t *data; - int i, len, plen, pos; - oma_tlv_t tlv; - PRINTF(">>> CREATE ? %d/%d\n", context.object_id, - context.object_instance_id); - - for(i = 0; i < object->count; i++) { - if((object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) == 0) { - /* allocate this instance */ - object->instances[i].flag |= LWM2M_INSTANCE_FLAG_USED; - object->instances[i].id = context.object_instance_id; - context.object_instance_index = i; - PRINTF("Created instance: %d\n", context.object_instance_id); - REST.set_response_status(response, CREATED_2_01); - instance = &object->instances[i]; - break; - } + int plen = coap_get_payload(request, &data); + if(plen > 0) { + LOG_DBG("Data: '"); + LOG_DBG_COAP_STRING((const char *)data, plen); + LOG_DBG_("'\n"); } + } + } - if(instance == NULL) { - /* could for some reason not create the instance */ - REST.set_response_status(response, NOT_ACCEPTABLE_4_06); - return; - } + /* PUT/POST - e.g. write will not send in offset here - Maybe in the future? */ + if((offset != NULL && *offset == 0) && + coap_is_option(request, COAP_OPTION_BLOCK1)) { + coap_get_header_block1(request, &bnum, &bmore, &bsize, &boffset); + context.offset = boffset; + } - plen = REST.get_request_payload(request, &data); - if(plen == 0) { - /* do nothing more */ - return; - } - PRINTF("Payload: "); - for(i = 0; i < plen; i++) { - PRINTF("%02x", data[i]); - } - PRINTF("\n"); - - pos = 0; - do { - len = oma_tlv_read(&tlv, (uint8_t *)&data[pos], plen - pos); - PRINTF("Found TLV type=%u id=%u len=%lu\n", - tlv.type, tlv.id, (unsigned long)tlv.length); - /* here we need to do callbacks or write value */ - if(tlv.type == OMA_TLV_TYPE_RESOURCE) { - context.resource_id = tlv.id; - const lwm2m_resource_t *rsc = get_resource(instance, &context); - if(rsc != NULL) { - /* write the value to the resource */ - if(lwm2m_object_is_resource_string(rsc)) { - PRINTF(" new string value for /%d/%d/%d = %.*s\n", - context.object_id, context.object_instance_id, - context.resource_id, (int)tlv.length, tlv.value); - lwm2m_object_set_resource_string(rsc, &context, - tlv.length, tlv.value); - } else if(lwm2m_object_is_resource_int(rsc)) { - PRINTF(" new int value for /%d/%d/%d = %" PRId32 "\n", - context.object_id, context.object_instance_id, - context.resource_id, oma_tlv_get_int32(&tlv)); - lwm2m_object_set_resource_int(rsc, &context, - oma_tlv_get_int32(&tlv)); - } else if(lwm2m_object_is_resource_floatfix(rsc)) { - int32_t value; - if(oma_tlv_float32_to_fix(&tlv, &value, LWM2M_FLOAT32_BITS)) { - PRINTF(" new float value for /%d/%d/%d = %" PRId32 "\n", - context.object_id, context.object_instance_id, - context.resource_id, value >> LWM2M_FLOAT32_BITS); - lwm2m_object_set_resource_floatfix(rsc, &context, value); - } else { - PRINTF(" new float value for /%d/%d/%d: FAILED\n", - context.object_id, context.object_instance_id, - context.resource_id); - } - } else if(lwm2m_object_is_resource_boolean(rsc)) { - PRINTF(" new boolean value for /%d/%d/%d = %" PRId32 "\n", - context.object_id, context.object_instance_id, - context.resource_id, oma_tlv_get_int32(&tlv)); - lwm2m_object_set_resource_boolean(rsc, &context, - oma_tlv_get_int32(&tlv) != 0); - } - } - } - pos = pos + len; - } while(len > 0 && pos < plen); + /* This is a discovery operation */ + switch(context.operation) { + case LWM2M_OP_DISCOVER: + /* Assume only one disco at a time... */ + success = perform_multi_resource_read_op(object, instance, &context); + break; + case LWM2M_OP_READ: + success = perform_multi_resource_read_op(object, instance, &context); + break; + case LWM2M_OP_WRITE: + success = perform_multi_resource_write_op(object, instance, &context, format); + break; + case LWM2M_OP_EXECUTE: + success = call_instance(instance, &context); + break; + case LWM2M_OP_DELETE: + if(object != NULL && object->impl != NULL && + object->impl->delete_instance != NULL) { + object->impl->delete_instance(context.object_instance_id, &success); +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif + } else { + success = LWM2M_STATUS_OPERATION_NOT_ALLOWED; } - return; + break; + default: + success = LWM2M_STATUS_OPERATION_NOT_ALLOWED; + break; } - if(depth == 3) { - const lwm2m_resource_t *resource = get_resource(instance, &context); - size_t content_len = 0; - if(resource == NULL) { - PRINTF("Error - do not have resource %d\n", context.resource_id); - REST.set_response_status(response, NOT_FOUND_4_04); - return; + if(success == LWM2M_STATUS_OK) { + /* Handle blockwise 1 */ + if(coap_is_option(request, COAP_OPTION_BLOCK1)) { + LOG_DBG("Setting BLOCK 1 num:%"PRIu32" o2:%"PRIu32" o:%"PRId32"\n", bnum, boffset, + (offset != NULL ? *offset : 0)); + coap_set_header_block1(response, bnum, 0, bsize); } - /* HANDLE PUT */ - if(method == METHOD_PUT) { - if(lwm2m_object_is_resource_callback(resource)) { - if(resource->value.callback.write != NULL) { - /* pick a reader ??? */ - if(format == LWM2M_TEXT_PLAIN) { - /* a string */ - const uint8_t *data; - int plen = REST.get_request_payload(request, &data); - context.reader = &lwm2m_plain_text_reader; - PRINTF("PUT Callback with data: '%.*s'\n", plen, data); - /* no specific reader for plain text */ - content_len = resource->value.callback.write(&context, data, plen, - buffer, preferred_size); - PRINTF("content_len:%u\n", (unsigned int)content_len); - REST.set_response_status(response, CHANGED_2_04); - } else { - PRINTF("PUT callback with format %d\n", format); - REST.set_response_status(response, NOT_ACCEPTABLE_4_06); - } - } else { - PRINTF("PUT - no write callback\n"); - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - } - } else { - PRINTF("PUT on non-callback resource!\n"); - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - } - /* HANDLE GET */ - } else if(method == METHOD_GET) { - if(lwm2m_object_is_resource_string(resource)) { - const uint8_t *value; - value = lwm2m_object_get_resource_string(resource, &context); - if(value != NULL) { - uint16_t len = lwm2m_object_get_resource_strlen(resource, &context); - PRINTF("Get string value: %.*s\n", (int)len, (char *)value); - content_len = context.writer->write_string(&context, buffer, - preferred_size, (const char *)value, len); - } - } else if(lwm2m_object_is_resource_int(resource)) { - int32_t value; - if(lwm2m_object_get_resource_int(resource, &context, &value)) { - content_len = context.writer->write_int(&context, buffer, preferred_size, value); - } - } else if(lwm2m_object_is_resource_floatfix(resource)) { - int32_t value; - if(lwm2m_object_get_resource_floatfix(resource, &context, &value)) { - /* export FLOATFIX */ - PRINTF("Exporting %d-bit fix as float: %" PRId32 "\n", - LWM2M_FLOAT32_BITS, value); - content_len = context.writer->write_float32fix(&context, buffer, - preferred_size, value, LWM2M_FLOAT32_BITS); - } - } else if(lwm2m_object_is_resource_callback(resource)) { - if(resource->value.callback.read != NULL) { - content_len = resource->value.callback.read(&context, - buffer, preferred_size); - } else { - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - return; - } - } - if(content_len > 0) { - REST.set_response_payload(response, buffer, content_len); - REST.set_header_content_type(response, content_type); - } else { - /* failed to produce output - it is an internal error */ - REST.set_response_status(response, INTERNAL_SERVER_ERROR_5_00); - } - /* Handle POST */ - } else if(method == METHOD_POST) { - if(lwm2m_object_is_resource_callback(resource)) { - if(resource->value.callback.exec != NULL) { - const uint8_t *data; - int plen = REST.get_request_payload(request, &data); - PRINTF("Execute Callback with data: '%.*s'\n", plen, data); - content_len = resource->value.callback.exec(&context, - data, plen, - buffer, preferred_size); - REST.set_response_status(response, CHANGED_2_04); + + if(context.outbuf->len > 0) { + LOG_DBG("["); + LOG_DBG_COAP_STRING(url, url_len); + LOG_DBG_("] replying with %u bytes\n", context.outbuf->len); + coap_set_payload(response, context.outbuf->buffer, context.outbuf->len); + coap_set_header_content_format(response, context.content_type); + + if(offset != NULL) { + LOG_DBG("Setting new offset: oo %"PRIu32 + ", no: %"PRIu32"\n", *offset, context.offset); + if(context.writer_flags & WRITER_HAS_MORE) { + *offset = context.offset; } else { - PRINTF("Execute callback - no exec callback\n"); - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); + /* this signals to CoAP that there is no more CoAP messages to expect */ + *offset = -1; } - } else { - PRINTF("Resource post but no callback resource\n"); - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); } - } - } else if(depth == 2) { - /* produce an instance response */ - if(method != METHOD_GET) { - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - } else if(instance == NULL) { - REST.set_response_status(response, NOT_FOUND_4_04); } else { - int rdlen; - if(accept == APPLICATION_LINK_FORMAT) { - rdlen = write_rd_link_data(object, instance, - (char *)buffer, preferred_size); - } else { - rdlen = write_rd_json_data(&context, object, instance, - (char *)buffer, preferred_size); - } - if(rdlen < 0) { - PRINTF("Failed to generate instance response\n"); - REST.set_response_status(response, SERVICE_UNAVAILABLE_5_03); - return; - } - REST.set_response_payload(response, buffer, rdlen); - if(accept == APPLICATION_LINK_FORMAT) { - REST.set_header_content_type(response, REST.type.APPLICATION_LINK_FORMAT); - } else { - REST.set_header_content_type(response, LWM2M_JSON); - } + LOG_DBG("["); + LOG_DBG_COAP_STRING(url, url_len); + LOG_DBG_("] no data in reply\n"); } - } else if(depth == 1) { - /* produce a list of instances */ - if(method != METHOD_GET) { - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - } else { - int rdlen; - PRINTF("Sending instance list for object %u\n", object->id); - /* TODO: if(accept == APPLICATION_LINK_FORMAT) { */ - rdlen = write_object_instances_link(object, (char *)buffer, preferred_size); - if(rdlen < 0) { - PRINTF("Failed to generate object response\n"); - REST.set_response_status(response, SERVICE_UNAVAILABLE_5_03); - return; - } - REST.set_header_content_type(response, REST.type.APPLICATION_LINK_FORMAT); - REST.set_response_payload(response, buffer, rdlen); + } else { + switch(success) { + case LWM2M_STATUS_FORBIDDEN: + coap_set_status_code(response, FORBIDDEN_4_03); + break; + case LWM2M_STATUS_NOT_FOUND: + coap_set_status_code(response, NOT_FOUND_4_04); + break; + case LWM2M_STATUS_OPERATION_NOT_ALLOWED: + coap_set_status_code(response, METHOD_NOT_ALLOWED_4_05); + break; + case LWM2M_STATUS_NOT_ACCEPTABLE: + coap_set_status_code(response, NOT_ACCEPTABLE_4_06); + break; + case LWM2M_STATUS_UNSUPPORTED_CONTENT_FORMAT: + coap_set_status_code(response, UNSUPPORTED_MEDIA_TYPE_4_15); + break; + default: + /* Failed to handle the request */ + coap_set_status_code(response, INTERNAL_SERVER_ERROR_5_00); + break; } + LOG_WARN("["); + LOG_WARN_COAP_STRING(url, url_len); + LOG_WARN("] resource failed: %s\n", get_status_as_string(success)); } + return COAP_HANDLER_STATUS_PROCESSED; } /*---------------------------------------------------------------------------*/ -void -lwm2m_engine_delete_handler(const lwm2m_object_t *object, void *request, - void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +void lwm2m_notify_object_observers(lwm2m_object_instance_t *obj, + uint16_t resource) { - int len; - const char *url; - lwm2m_context_t context; - - len = REST.get_url(request, &url); - PRINTF("*** DELETE URI:'%.*s' called... - responding with DELETED.\n", - len, url); - len = lwm2m_engine_parse_context(object, url, len, &context); - PRINTF("Context: %u/%u/%u found: %d\n", context.object_id, - context.object_instance_id, context.resource_id, len); - - REST.set_response_status(response, DELETED_2_02); + char path[20]; /* 60000/60000/60000 */ + if(obj != NULL) { + snprintf(path, 20, "%d/%d/%d", obj->object_id, obj->instance_id, resource); + coap_notify_observers_sub(NULL, path); + } } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/lwm2m-engine.h b/os/services/lwm2m/lwm2m-engine.h index 5512a326d114f86eea3569a3e403ace8f7c6eb49..62a667e9916392da036650112a50c2aad184f53b 100644 --- a/os/services/lwm2m/lwm2m-engine.h +++ b/os/services/lwm2m/lwm2m-engine.h @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ @@ -52,31 +52,68 @@ /* LWM2M / CoAP Content-Formats */ typedef enum { LWM2M_TEXT_PLAIN = 1541, - LWM2M_TLV = 1542, - LWM2M_JSON = 1543, - LWM2M_OPAQUE = 1544 + LWM2M_TLV = 11542, + LWM2M_JSON = 11543, + LWM2M_OLD_TLV = 1542, + LWM2M_OLD_JSON = 1543, + LWM2M_OLD_OPAQUE = 1544 } lwm2m_content_format_t; void lwm2m_engine_init(void); -void lwm2m_engine_register_default_objects(void); -void lwm2m_engine_use_bootstrap_server(int use); -void lwm2m_engine_use_registration_server(int use); -void lwm2m_engine_register_with_server(const uip_ipaddr_t *server, uint16_t port); -void lwm2m_engine_register_with_bootstrap_server(const uip_ipaddr_t *server, uint16_t port); -const lwm2m_object_t *lwm2m_engine_get_object(uint16_t id); +int lwm2m_engine_set_rd_data(lwm2m_buffer_t *outbuf, int block); -int lwm2m_engine_register_object(const lwm2m_object_t *object); +typedef lwm2m_status_t +(* lwm2m_object_instance_callback_t)(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx); +typedef int +(* lwm2m_resource_dim_callback_t)(lwm2m_object_instance_t *object, + uint16_t resource_id); -void lwm2m_engine_handler(const lwm2m_object_t *object, - void *request, void *response, - uint8_t *buffer, uint16_t preferred_size, - int32_t *offset); +#define LWM2M_OBJECT_INSTANCE_NONE 0xffff + +struct lwm2m_object_instance { + lwm2m_object_instance_t *next; + uint16_t object_id; + uint16_t instance_id; + /* an array of resource IDs for discovery, etc */ + const lwm2m_resource_id_t *resource_ids; + uint16_t resource_count; + /* the callback for requests */ + lwm2m_object_instance_callback_t callback; + lwm2m_resource_dim_callback_t resource_dim_callback; +}; + +typedef struct { + uint16_t object_id; + lwm2m_object_instance_t *(* create_instance)(uint16_t instance_id, + lwm2m_status_t *status); + int (* delete_instance)(uint16_t instance_id, lwm2m_status_t *status); + lwm2m_object_instance_t *(* get_first)(lwm2m_status_t *status); + lwm2m_object_instance_t *(* get_next)(lwm2m_object_instance_t *instance, + lwm2m_status_t *status); + lwm2m_object_instance_t *(* get_by_id)(uint16_t instance_id, + lwm2m_status_t *status); +} lwm2m_object_impl_t; + +typedef struct lwm2m_object lwm2m_object_t; +struct lwm2m_object { + lwm2m_object_t *next; + const lwm2m_object_impl_t *impl; +}; + +lwm2m_object_instance_t *lwm2m_engine_get_instance_buffer(void); + +int lwm2m_engine_has_instance(uint16_t object_id, uint16_t instance_id); +int lwm2m_engine_add_object(lwm2m_object_instance_t *object); +void lwm2m_engine_remove_object(lwm2m_object_instance_t *object); +int lwm2m_engine_add_generic_object(lwm2m_object_t *object); +void lwm2m_engine_remove_generic_object(lwm2m_object_t *object); +void lwm2m_notify_object_observers(lwm2m_object_instance_t *obj, + uint16_t resource); + +void lwm2m_engine_set_opaque_callback(lwm2m_context_t *ctx, lwm2m_write_opaque_callback cb); -void lwm2m_engine_delete_handler(const lwm2m_object_t *object, - void *request, void *response, - uint8_t *buffer, uint16_t preferred_size, - int32_t *offset); #endif /* LWM2M_ENGINE_H */ /** @} */ diff --git a/os/services/lwm2m/lwm2m-firmware.c b/os/services/lwm2m/lwm2m-firmware.c new file mode 100644 index 0000000000000000000000000000000000000000..87815d6841cdd0566ab9941060d4592b9a02f8a7 --- /dev/null +++ b/os/services/lwm2m/lwm2m-firmware.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \addtogroup lwm2m + * @{ + * + * Code for firmware object of lwm2m + * + */ + +#include "lwm2m-engine.h" +#include "lwm2m-firmware.h" +#include "coap.h" +#include <inttypes.h> +#include <string.h> + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-fw" +#define LOG_LEVEL LOG_LEVEL_LWM2M + +#define UPDATE_PACKAGE 0 +#define UPDATE_PACKAGE_URI 1 +#define UPDATE_UPDATE 2 +#define UPDATE_STATE 3 +#define UPDATE_RESULT 5 + +#define STATE_IDLE 1 +#define STATE_DOWNLOADING 2 +#define STATE_DOWNLOADED 3 + +#define RESULT_DEFAULT 0 +#define RESULT_SUCCESS 1 +#define RESULT_NO_STORAGE 2 +#define RESULT_OUT_OF_MEM 3 +#define RESULT_CONNECTION_LOST 4 +#define RESULT_CRC_FAILED 5 +#define RESULT_UNSUPPORTED_FW 6 +#define RESULT_INVALID_URI 7 + + +static uint8_t state = STATE_IDLE; +static uint8_t result = RESULT_DEFAULT; + +static lwm2m_object_instance_t reg_object; + +static const lwm2m_resource_id_t resources[] = + { WO(UPDATE_PACKAGE), + WO(UPDATE_PACKAGE_URI), + RO(UPDATE_STATE), + RO(UPDATE_RESULT), + EX(UPDATE_UPDATE) + }; + +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) +{ + uint32_t num; + uint8_t more; + uint16_t size; + uint32_t offset; + + LOG_DBG("Got request at: %d/%d/%d lv:%d\n", ctx->object_id, + ctx->object_instance_id, ctx->resource_id, ctx->level); + + if(ctx->level == 1 || ctx->level == 2) { + /* Should not happen - as it will be taken care of by the lwm2m engine itself. */ + return LWM2M_STATUS_ERROR; + } + + if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case UPDATE_STATE: + lwm2m_object_write_int(ctx, state); /* 1 means idle */ + return LWM2M_STATUS_OK; + case UPDATE_RESULT: + lwm2m_object_write_int(ctx, result); /* 0 means default */ + return LWM2M_STATUS_OK; + } + } else if(ctx->operation == LWM2M_OP_WRITE) { + + if(LOG_DBG_ENABLED) { + if(coap_get_header_block1(ctx->request, &num, &more, &size, &offset)) { + LOG_DBG("CoAP BLOCK1: %"PRIu32"/%u/%u offset:%"PRIu32 + " LWM2M CTX->offset=%"PRIu32"\n", + num, more, size, offset, ctx->offset); + } + } + + switch(ctx->resource_id) { + case UPDATE_PACKAGE: + /* The firmware is written */ + LOG_DBG("Firmware received: %"PRIu32" %d fin:%d\n", ctx->offset, + (int)ctx->inbuf->size, lwm2m_object_is_final_incoming(ctx)); + if(lwm2m_object_is_final_incoming(ctx)) { + state = STATE_DOWNLOADED; + } else { + state = STATE_DOWNLOADING; + } + return LWM2M_STATUS_OK; + case UPDATE_PACKAGE_URI: + /* The firmware URI is written */ + LOG_DBG("Firmware URI received: %"PRIu32" %d fin:%d\n", ctx->offset, + (int)ctx->inbuf->size, lwm2m_object_is_final_incoming(ctx)); + if(LOG_DBG_ENABLED) { + int i; + LOG_DBG("Data: '"); + for(i = 0; i < ctx->inbuf->size; i++) { + LOG_DBG_("%c", ctx->inbuf->buffer[i]); + } + LOG_DBG_("'\n"); + } + return LWM2M_STATUS_OK; + } + } else if(ctx->operation == LWM2M_OP_EXECUTE && ctx->resource_id == UPDATE_UPDATE) { + /* Perform the update operation */ + if(state == STATE_DOWNLOADED) { + return LWM2M_STATUS_OK; + } + /* Failure... */ + } + return LWM2M_STATUS_ERROR; +} + +/*---------------------------------------------------------------------------*/ +void +lwm2m_firmware_init(void) +{ + reg_object.object_id = 5; + reg_object.instance_id = 0; + reg_object.callback = lwm2m_callback; + reg_object.resource_ids = resources; + reg_object.resource_count = sizeof(resources) / sizeof(lwm2m_resource_id_t); + + lwm2m_engine_add_object(®_object); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-firmware.h b/os/services/lwm2m/lwm2m-firmware.h new file mode 100644 index 0000000000000000000000000000000000000000..2b83922cd3fd65059018b494634eeb39d5aee0e2 --- /dev/null +++ b/os/services/lwm2m/lwm2m-firmware.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, SICS Swedish ICT AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \addtogroup lwm2m + * @{ + * + * Code for firmware object of lwm2m + * + */ + +#ifndef LWM2M_FIRMWARE_H_ +#define LWM2M_FIRMWARE_H_ + +void lwm2m_firmware_init(void); + +#endif /* LWM2M_FIRMWARE_H_ */ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-json.c b/os/services/lwm2m/lwm2m-json.c index 8924ceb8c28388f31bd21b854163a85911caa973..8ad8be9c44b286900efb33b21067c918f329933c 100644 --- a/os/services/lwm2m/lwm2m-json.c +++ b/os/services/lwm2m/lwm2m-json.c @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ @@ -38,6 +38,7 @@ * Implementation of the Contiki OMA LWM2M JSON writer * \author * Joakim Nohlgård <joakim.nohlgard@eistec.se> + * Joakim Eriksson <joakime@sics.se> added JSON reader parts */ #include "lwm2m-object.h" @@ -48,43 +49,201 @@ #include <stdint.h> #include <inttypes.h> -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-json" +#define LOG_LEVEL LOG_LEVEL_NONE +/*---------------------------------------------------------------------------*/ + +/* {"e":[{"n":"111/1","v":123},{"n":"111/2","v":42}]} */ + +/* Begin String */ +#define T_NONE 0 +#define T_STRING_B 1 +#define T_STRING 2 +#define T_NAME 4 +#define T_VNUM 5 +#define T_OBJ 6 +#define T_VAL 7 + +/* Simlified JSON style reader for reading in values from a LWM2M JSON + string */ +int +lwm2m_json_next_token(lwm2m_context_t *ctx, struct json_data *json) +{ + int pos = ctx->inbuf->pos; + uint8_t type = T_NONE; + uint8_t vpos_start = 0; + uint8_t vpos_end = 0; + uint8_t cont; + uint8_t wscount = 0; + + json->name_len = 0; + json->value_len = 0; + + cont = 1; + /* We will be either at start, or at a specific position */ + while(pos < ctx->inbuf->size && cont) { + uint8_t c = ctx->inbuf->buffer[pos++]; + switch(c) { + case '{': type = T_OBJ; break; + case '}': + case ',': + if(type == T_VAL || type == T_STRING) { + json->value = &ctx->inbuf->buffer[vpos_start]; + json->value_len = vpos_end - vpos_start - wscount; + type = T_NONE; + cont = 0; + } + wscount = 0; + break; + case '\\': + /* stuffing */ + if(pos < ctx->inbuf->size) { + pos++; + vpos_end = pos; + } + break; + case '"': + if(type == T_STRING_B) { + type = T_STRING; + vpos_end = pos - 1; + wscount = 0; + } else { + type = T_STRING_B; + vpos_start = pos; + } + break; + case ':': + if(type == T_STRING) { + json->name = &ctx->inbuf->buffer[vpos_start]; + json->name_len = vpos_end - vpos_start; + vpos_start = vpos_end = pos; + type = T_VAL; + } else { + /* Could be in string or at illegal pos */ + if(type != T_STRING_B) { + LOG_DBG("ERROR - illegal ':'\n"); + } + } + break; + /* ignore whitespace */ + case ' ': + case '\n': + case '\t': + if(type != T_STRING_B) { + if(vpos_start == pos - 1) { + vpos_start = pos; + } else { + wscount++; + } + } + default: + vpos_end = pos; + } + } + if(cont == 0 && pos < ctx->inbuf->size) { + ctx->inbuf->pos = pos; + } + /* OK if cont == 0 othewise we failed */ + return cont == 0 && pos < ctx->inbuf->size; +} +/*---------------------------------------------------------------------------*/ +static size_t +init_write(lwm2m_context_t *ctx) +{ + int len = snprintf((char *)&ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, "{\"bn\":\"/%u/%u/\",\"e\":[", + ctx->object_id, ctx->object_instance_id); + ctx->writer_flags = 0; /* set flags to zero */ + if((len < 0) || (len >= ctx->outbuf->size)) { + return 0; + } + return len; +} +/*---------------------------------------------------------------------------*/ +static size_t +end_write(lwm2m_context_t *ctx) +{ + int len = snprintf((char *)&ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, "]}"); + if((len < 0) || (len >= ctx->outbuf->size - ctx->outbuf->len)) { + return 0; + } + return len; +} +/*---------------------------------------------------------------------------*/ +static size_t +enter_sub(lwm2m_context_t *ctx) +{ + /* set some flags in state */ + LOG_DBG("Enter sub-resource rsc=%d\n", ctx->resource_id); + ctx->writer_flags |= WRITER_RESOURCE_INSTANCE; + return 0; +} +/*---------------------------------------------------------------------------*/ +static size_t +exit_sub(lwm2m_context_t *ctx) +{ + /* clear out state info */ + LOG_DBG("Exit sub-resource rsc=%d\n", ctx->resource_id); + ctx->writer_flags &= ~WRITER_RESOURCE_INSTANCE; + return 0; +} /*---------------------------------------------------------------------------*/ static size_t -write_boolean(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_boolean(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int value) { - int len = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"bv\":%s}]}\n", ctx->resource_id, value ? "true" : "false"); + char *sep = (ctx->writer_flags & WRITER_OUTPUT_VALUE) ? "," : ""; + int len; + if(ctx->writer_flags & WRITER_RESOURCE_INSTANCE) { + len = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u/%u\",\"bv\":%s}", sep, ctx->resource_id, ctx->resource_instance_id, value ? "true" : "false"); + } else { + len = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u\",\"bv\":%s}", sep, ctx->resource_id, value ? "true" : "false"); + } if((len < 0) || (len >= outlen)) { return 0; } + LOG_DBG("JSON: Write bool:%s\n", outbuf); + + ctx->writer_flags |= WRITER_OUTPUT_VALUE; return len; } /*---------------------------------------------------------------------------*/ static size_t -write_int(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_int(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value) { - int len = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"v\":%" PRId32 "}]}\n", ctx->resource_id, value); + char *sep = (ctx->writer_flags & WRITER_OUTPUT_VALUE) ? "," : ""; + int len; + if(ctx->writer_flags & WRITER_RESOURCE_INSTANCE) { + len = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u/%u\",\"v\":%"PRId32"}", sep, ctx->resource_id, ctx->resource_instance_id, value); + } else { + len = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u\",\"v\":%"PRId32"}", sep, ctx->resource_id, value); + } if((len < 0) || (len >= outlen)) { return 0; } + LOG_DBG("Write int:%s\n", outbuf); + + ctx->writer_flags |= WRITER_OUTPUT_VALUE; return len; } /*---------------------------------------------------------------------------*/ static size_t -write_float32fix(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_float32fix(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value, int bits) { + char *sep = (ctx->writer_flags & WRITER_OUTPUT_VALUE) ? "," : ""; size_t len = 0; int res; - res = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"v\":", ctx->resource_id); + if(ctx->writer_flags & WRITER_RESOURCE_INSTANCE) { + res = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u/%u\",\"v\":", sep, ctx->resource_id, ctx->resource_instance_id); + } else { + res = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u\",\"v\":", sep, ctx->resource_id); + } if(res <= 0 || res >= outlen) { return 0; } @@ -96,23 +255,31 @@ write_float32fix(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, } len += res; outlen -= res; - res = snprintf((char *)&outbuf[len], outlen, "}]}\n"); + res = snprintf((char *)&outbuf[len], outlen, "}"); if((res <= 0) || (res >= outlen)) { return 0; } len += res; + ctx->writer_flags |= WRITER_OUTPUT_VALUE; return len; } /*---------------------------------------------------------------------------*/ static size_t -write_string(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_string(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, const char *value, size_t stringlen) { + char *sep = (ctx->writer_flags & WRITER_OUTPUT_VALUE) ? "," : ""; size_t i; size_t len = 0; int res; - PRINTF("{\"e\":[{\"n\":\"%u\",\"sv\":\"", ctx->resource_id); - res = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"sv\":\"", ctx->resource_id); + LOG_DBG("{\"n\":\"%u\",\"sv\":\"", ctx->resource_id); + if(ctx->writer_flags & WRITER_RESOURCE_INSTANCE) { + res = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u/%u\",\"sv\":\"", sep, + ctx->resource_id, ctx->resource_instance_id); + } else { + res = snprintf((char *)outbuf, outlen, "%s{\"n\":\"%u\",\"sv\":\"", sep, + ctx->resource_id); + } if(res < 0 || res >= outlen) { return 0; } @@ -121,7 +288,7 @@ write_string(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, /* Escape special characters */ /* TODO: Handle UTF-8 strings */ if(value[i] < '\x20') { - PRINTF("\\x%x", value[i]); + LOG_DBG_("\\x%x", value[i]); res = snprintf((char *)&outbuf[len], outlen - len, "\\x%x", value[i]); if((res < 0) || (res >= (outlen - len))) { return 0; @@ -129,34 +296,44 @@ write_string(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, len += res; continue; } else if(value[i] == '"' || value[i] == '\\') { - PRINTF("\\"); + LOG_DBG_("\\"); outbuf[len] = '\\'; ++len; if(len >= outlen) { return 0; } } - PRINTF("%c", value[i]); + LOG_DBG_("%c", value[i]); outbuf[len] = value[i]; ++len; if(len >= outlen) { return 0; } } - PRINTF("\"}]}\n"); - res = snprintf((char *)&outbuf[len], outlen - len, "\"}]}\n"); + LOG_DBG_("\"}\n"); + res = snprintf((char *)&outbuf[len], outlen - len, "\"}"); if((res < 0) || (res >= (outlen - len))) { return 0; } + + LOG_DBG("JSON: Write string:%s\n", outbuf); + len += res; + ctx->writer_flags |= WRITER_OUTPUT_VALUE; return len; } /*---------------------------------------------------------------------------*/ const lwm2m_writer_t lwm2m_json_writer = { + init_write, + end_write, + enter_sub, + exit_sub, write_int, write_string, write_float32fix, write_boolean }; +/*---------------------------------------------------------------------------*/ + /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/lwm2m-json.h b/os/services/lwm2m/lwm2m-json.h index bc1a1e32ab2fe8edcfef391eb7eb71de0260a9a6..8267d02465741bf991eb8bb7d9da481c3cc02b0f 100644 --- a/os/services/lwm2m/lwm2m-json.h +++ b/os/services/lwm2m/lwm2m-json.h @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ @@ -45,7 +45,17 @@ #include "lwm2m-object.h" +struct json_data { + uint8_t type; /* S,B,V */ + uint8_t *name; + uint8_t *value; + uint8_t name_len; + uint8_t value_len; +}; + extern const lwm2m_writer_t lwm2m_json_writer; +int lwm2m_json_next_token(lwm2m_context_t *ctx, struct json_data *json); + #endif /* LWM2M_JSON_H_ */ /** @} */ diff --git a/os/services/lwm2m/lwm2m-object.c b/os/services/lwm2m/lwm2m-object.c deleted file mode 100644 index 2f5ddb6edca44c322953373c3a2509f1dcde8036..0000000000000000000000000000000000000000 --- a/os/services/lwm2m/lwm2m-object.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright (c) 2015, Yanzi Networks AB. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \addtogroup oma-lwm2m - * @{ - * - */ - -/** - * \file - * Implementation of the Contiki OMA LWM2M object API - * \author - * Joakim Eriksson <joakime@sics.se> - * Niclas Finne <nfi@sics.se> - */ - -#include "lwm2m-object.h" -#include <string.h> -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_is_resource_string(const lwm2m_resource_t *resource) -{ - if(resource == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VALUE || - resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE || - resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY) { - return 1; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -const uint8_t * -lwm2m_object_get_resource_string(const lwm2m_resource_t *resource, - const lwm2m_context_t *context) -{ - if(resource == NULL || context == NULL) { - return NULL; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VALUE) { - return resource->value.string.value; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE) { - return *(resource->value.stringvar.var); - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.stringvararr.count) { - return resource->value.stringvararr.var + - resource->value.stringvararr.size * context->object_instance_index; - } - return NULL; - } - /* Not a string */ - return NULL; -} -/*---------------------------------------------------------------------------*/ -uint16_t -lwm2m_object_get_resource_strlen(const lwm2m_resource_t *resource, - const lwm2m_context_t *context) -{ - if(resource == NULL || context == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VALUE) { - return resource->value.string.len; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE) { - return *(resource->value.stringvar.len); - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.stringvararr.count) { - return resource->value.stringvararr.len[context->object_instance_index]; - } - return 0; - } - /* Not a string */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_set_resource_string(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - uint16_t len, const uint8_t *string) -{ - if(resource == NULL || context == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE) { - if(len > resource->value.stringvar.size) { - /* Too large */ - return 0; - } - memcpy(resource->value.stringvar.var, string, len); - *(resource->value.stringvar.len) = len; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.stringvararr.count && - len <= resource->value.stringvararr.size) { - memcpy(resource->value.stringvararr.var + - resource->value.stringvararr.size * context->object_instance_index, - string, len); - resource->value.stringvararr.len[context->object_instance_index] = len; - return 1; - } - return 0; - } - /* Not a string variable */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_is_resource_int(const lwm2m_resource_t *resource) -{ - if(resource == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VALUE || - resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE || - resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE_ARRAY) { - return 1; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_get_resource_int(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t *value) -{ - if(resource == NULL || context == NULL || value == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VALUE) { - *value = resource->value.integer.value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE) { - *value = *(resource->value.integervar.var); - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.integervararr.count) { - *value = resource->value.integervararr.var[context->object_instance_index]; - return 1; - } - return 0; - } - /* Not an integer */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_set_resource_int(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t value) -{ - if(resource == NULL || context == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE) { - *(resource->value.integervar.var) = value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_INT_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.integervararr.count) { - resource->value.integervararr.var[context->object_instance_index] = - value; - return 1; - } - return 0; - } - /* Not an integer variable */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_is_resource_floatfix(const lwm2m_resource_t *resource) -{ - if(resource == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VALUE || - resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE || - resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE_ARRAY) { - return 1; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_get_resource_floatfix(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t *value) -{ - if(resource == NULL || context == NULL || value == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VALUE) { - *value = resource->value.floatfix.value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE) { - *value = *(resource->value.floatfixvar.var); - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.floatfixvararr.count) { - *value = resource->value.floatfixvararr.var[context->object_instance_index]; - return 1; - } - return 0; - } - /* Not an float */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_set_resource_floatfix(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t value) -{ - if(resource == NULL || context == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE) { - *(resource->value.floatfixvar.var) = value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.floatfixvararr.count) { - resource->value.floatfixvararr.var[context->object_instance_index] = - value; - return 1; - } - return 0; - } - /* Not an float variable */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_is_resource_boolean(const lwm2m_resource_t *resource) -{ - if(resource == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VALUE || - resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE || - resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE_ARRAY) { - return 1; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_get_resource_boolean(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int *value) -{ - if(resource == NULL || context == NULL || value == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VALUE) { - *value = resource->value.boolean.value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE) { - *value = *(resource->value.booleanvar.var); - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.booleanvararr.count) { - *value = resource->value.booleanvararr.var[context->object_instance_index]; - return 1; - } - return 0; - } - /* Not a boolean */ - return 0; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_object_set_resource_boolean(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int value) -{ - if(resource == NULL || context == NULL) { - return 0; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE) { - *(resource->value.booleanvar.var) = value; - return 1; - } - if(resource->type == LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE_ARRAY) { - if(context->object_instance_index < resource->value.booleanvararr.count) { - resource->value.booleanvararr.var[context->object_instance_index] = - value; - return 1; - } - return 0; - } - /* Not a boolean variable */ - return 0; -} -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/os/services/lwm2m/lwm2m-object.h b/os/services/lwm2m/lwm2m-object.h index a5ff53ac47fd0e46fade2885656eb207e61c8dc8..c6c582a35287dac48140768d2072c418fe7e8d41 100644 --- a/os/services/lwm2m/lwm2m-object.h +++ b/os/services/lwm2m/lwm2m-object.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,15 +34,15 @@ */ /** - * \defgroup oma-lwm2m An implementation of OMA LWM2M + * \defgroup lwm2m An implementation of LWM2M * @{ * - * This application is an implementation of OMA Lightweight M2M. + * This is an implementation of OMA Lightweight M2M (LWM2M). */ /** * \file - * Header file for the Contiki OMA LWM2M object API + * Header file for the LWM2M object API * \author * Joakim Eriksson <joakime@sics.se> * Niclas Finne <nfi@sics.se> @@ -51,8 +51,24 @@ #ifndef LWM2M_OBJECT_H_ #define LWM2M_OBJECT_H_ -#include "net/app-layer/coap/rest-engine.h" -#include "net/app-layer/coap/coap-observe.h" +#include "coap.h" +#include "coap-observe.h" + +/* Operation permissions on the resources - read/write/execute */ +#define LWM2M_RESOURCE_READ 0x10000 +#define LWM2M_RESOURCE_WRITE 0x20000 +#define LWM2M_RESOURCE_EXECUTE 0x40000 +#define LWM2M_RESOURCE_OP_MASK 0x70000 + +/* The resource id type of lwm2m objects - 16 bits for the ID - the rest + is flags */ +typedef uint32_t lwm2m_resource_id_t; + +/* Defines for the resource definition array */ +#define RO(x) (x | LWM2M_RESOURCE_READ) +#define WO(x) (x | LWM2M_RESOURCE_WRITE) +#define RW(x) (x | LWM2M_RESOURCE_READ | LWM2M_RESOURCE_WRITE) +#define EX(x) (x | LWM2M_RESOURCE_EXECUTE) #define LWM2M_OBJECT_SECURITY_ID 0 #define LWM2M_OBJECT_SERVER_ID 1 @@ -63,291 +79,281 @@ #define LWM2M_OBJECT_LOCATION_ID 6 #define LWM2M_OBJECT_CONNECTIVITY_STATISTICS_ID 7 -#define LWM2M_SECURITY_SERVER_URI 0 -#define LWM2M_SECURITY_BOOTSTRAP_SERVER 1 -#define LWM2M_SECURITY_MODE 2 -#define LWM2M_SECURITY_CLIENT_PKI 3 -#define LWM2M_SECURITY_SERVER_PKI 4 -#define LWM2M_SECURITY_KEY 5 -#define LWM2M_SECURITY_SHORT_SERVER_ID 10 - -/* Pre-shared key mode */ -#define LWM2M_SECURITY_MODE_PSK 0 -/* Raw Public Key mode */ -#define LWM2M_SECURITY_MODE_RPK 1 -/* Certificate mode */ -#define LWM2M_SECURITY_MODE_CERTIFICATE 2 -/* NoSec mode */ -#define LWM2M_SECURITY_MODE_NOSEC 3 - -#define LWM2M_OBJECT_STR_HELPER(x) (uint8_t *) #x -#define LWM2M_OBJECT_STR(x) LWM2M_OBJECT_STR_HELPER(x) - -#define LWM2M_OBJECT_PATH_STR_HELPER(x) #x -#define LWM2M_OBJECT_PATH_STR(x) LWM2M_OBJECT_PATH_STR_HELPER(x) - -struct lwm2m_reader; -struct lwm2m_writer; +typedef enum { + LWM2M_OP_NONE, + LWM2M_OP_READ, + LWM2M_OP_DISCOVER, + LWM2M_OP_WRITE, + LWM2M_OP_WRITE_ATTR, + LWM2M_OP_EXECUTE, + LWM2M_OP_CREATE, + LWM2M_OP_DELETE +} lwm2m_operation_t; + +typedef enum { + LWM2M_STATUS_OK, + + /* Internal server error */ + LWM2M_STATUS_ERROR, + /* Error from writer */ + LWM2M_STATUS_WRITE_ERROR, + /* Error from reader */ + LWM2M_STATUS_READ_ERROR, + + LWM2M_STATUS_BAD_REQUEST, + LWM2M_STATUS_UNAUTHORIZED, + LWM2M_STATUS_FORBIDDEN, + LWM2M_STATUS_NOT_FOUND, + LWM2M_STATUS_OPERATION_NOT_ALLOWED, + LWM2M_STATUS_NOT_ACCEPTABLE, + LWM2M_STATUS_UNSUPPORTED_CONTENT_FORMAT, + + LWM2M_STATUS_NOT_IMPLEMENTED, + LWM2M_STATUS_SERVICE_UNAVAILABLE, +} lwm2m_status_t; + +/* remember that we have already output a value - can be between two block's */ +#define WRITER_OUTPUT_VALUE 1 +#define WRITER_RESOURCE_INSTANCE 2 +#define WRITER_HAS_MORE 4 + +typedef struct lwm2m_reader lwm2m_reader_t; +typedef struct lwm2m_writer lwm2m_writer_t; + +typedef struct lwm2m_object_instance lwm2m_object_instance_t; + +typedef struct { + uint16_t len; /* used for current length of the data in the buffer */ + uint16_t pos; /* position in the buffer - typically write position or similar */ + uint16_t size; + uint8_t *buffer; +} lwm2m_buffer_t; + /* Data model for OMA LWM2M objects */ typedef struct lwm2m_context { uint16_t object_id; uint16_t object_instance_id; uint16_t resource_id; - uint8_t object_instance_index; + uint16_t resource_instance_id; + uint8_t resource_index; - /* TODO - add uint16_t resource_instance_id */ + uint8_t resource_instance_index; /* for use when stepping to next sub-resource if having multiple */ + uint8_t level; /* 0/1/2/3 = 3 = resource */ + lwm2m_operation_t operation; + + coap_message_t *request; + coap_message_t *response; + + unsigned int content_type; + lwm2m_buffer_t *outbuf; + lwm2m_buffer_t *inbuf; - const struct lwm2m_reader *reader; - const struct lwm2m_writer *writer; + uint8_t out_mark_pos_oi; /* mark pos for last object instance */ + uint8_t out_mark_pos_ri; /* mark pos for last resource instance */ + + uint32_t offset; /* If we do blockwise - this needs to change */ + + /* Info on last_instance read/write */ + uint16_t last_instance; + uint16_t last_value_len; + + uint8_t writer_flags; /* flags for reader/writer */ + const lwm2m_reader_t *reader; + const lwm2m_writer_t *writer; } lwm2m_context_t; /* LWM2M format writer for the various formats supported */ -typedef struct lwm2m_writer { - size_t (* write_int)(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value); - size_t (* write_string)(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, const char *value, size_t strlen); - size_t (* write_float32fix)(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value, int bits); - size_t (* write_boolean)(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int value); -} lwm2m_writer_t; - -typedef struct lwm2m_reader { - size_t (* read_int)(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value); - size_t (* read_string)(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t strlen); - size_t (* read_float32fix)(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits); - size_t (* read_boolean)(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value); -} lwm2m_reader_t; - -typedef struct lwm2m_value_callback { - int (* read)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen); - int (* write)(lwm2m_context_t *ctx, - const uint8_t *buffer, size_t len, - uint8_t *outbuf, size_t outlen); - int (* exec)(lwm2m_context_t *ctx, const uint8_t *arg, size_t len, - uint8_t *outbuf, size_t outlen); -} lwm2m_value_callback_t; - -#define LWM2M_RESOURCE_TYPE_STR_VALUE 1 -#define LWM2M_RESOURCE_TYPE_STR_VARIABLE 2 -#define LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY 3 -#define LWM2M_RESOURCE_TYPE_INT_VALUE 4 -#define LWM2M_RESOURCE_TYPE_INT_VARIABLE 5 -#define LWM2M_RESOURCE_TYPE_INT_VARIABLE_ARRAY 6 -#define LWM2M_RESOURCE_TYPE_FLOATFIX_VALUE 7 -#define LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE 8 -#define LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE_ARRAY 9 -#define LWM2M_RESOURCE_TYPE_BOOLEAN_VALUE 10 -#define LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE 11 -#define LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE_ARRAY 12 -#define LWM2M_RESOURCE_TYPE_CALLBACK 16 -#define LWM2M_RESOURCE_TYPE_INSTANCES 17 - -typedef struct lwm2m_resource { - uint16_t id; - uint8_t type; /* indicate value type and multi-instance resource */ - union { - struct { - uint16_t len; - const uint8_t *value; - } string; - struct { - uint16_t size; - uint16_t *len; - uint8_t **var; - } stringvar; - struct { - uint16_t count; - uint16_t size; - /* string var array with counting entries */ - uint16_t *len; - uint8_t *var; - } stringvararr; - struct { - int32_t value; - } integer; - struct { - int32_t *var; - } integervar; - struct { - /* used for multiple instances (dynamic) NOTE: this is an index into - the instance so having two instances means that there is need for - allocation of two ints here */ - uint16_t count; - int32_t *var; /* used as an array? */ - } integervararr; - struct { - int32_t value; - } floatfix; - struct { - int32_t *var; - } floatfixvar; - struct { - uint16_t count; - int32_t *var; - } floatfixvararr; - struct { - int value; - } boolean; - struct { - int *var; - } booleanvar; - struct { - uint16_t count; - int *var; - } booleanvararr; - lwm2m_value_callback_t callback; - /* lwm2m_resource *resources[]; TO BE ADDED LATER*/ - } value; -} lwm2m_resource_t; - -#define LWM2M_INSTANCE_FLAG_USED 1 - -typedef struct lwm2m_instance { - uint16_t id; - uint16_t count; - uint16_t flag; - const lwm2m_resource_t *resources; -} lwm2m_instance_t; - -typedef struct lwm2m_object { - uint16_t id; - uint16_t count; - const char *path; - resource_t *coap_resource; - lwm2m_instance_t *instances; -} lwm2m_object_t; - -#define LWM2M_RESOURCES(name, ...) \ - static const lwm2m_resource_t name[] = { __VA_ARGS__ } - -#define LWM2M_RESOURCE_STRING(id, s) \ - { id, LWM2M_RESOURCE_TYPE_STR_VALUE, .value.string.len = sizeof(s) - 1, .value.string.value = (uint8_t *) s } - -#define LWM2M_RESOURCE_STRING_VAR(id, s, l, v) \ - { id, LWM2M_RESOURCE_TYPE_STR_VARIABLE, .value.stringvar.size = (s), .value.stringvar.len = (l), .value.stringvar.var = (v) } - -#define LWM2M_RESOURCE_STRING_VAR_ARR(id, c, s, l, v) \ - { id, LWM2M_RESOURCE_TYPE_STR_VARIABLE_ARRAY, .value.stringvararr.count = c, .value.stringvararr.size = s, .value.stringvararr.len = l, .value.stringvararr.var = (uint8_t *) v } - -#define LWM2M_RESOURCE_INTEGER(id, v) \ - { id, LWM2M_RESOURCE_TYPE_INT_VALUE, .value.integer.value = (v) } - -#define LWM2M_RESOURCE_INTEGER_VAR(id, v) \ - { id, LWM2M_RESOURCE_TYPE_INT_VARIABLE, .value.integervar.var = (v) } - -#define LWM2M_RESOURCE_INTEGER_VAR_ARR(id, c, v) \ - { id, LWM2M_RESOURCE_TYPE_INT_VARIABLE_ARRAY, .value.integervararr.count = (c), .value.integervararr.var = (v) } - -#define LWM2M_RESOURCE_FLOATFIX(id, v) \ - { id, LWM2M_RESOURCE_TYPE_FLOATFIX_VALUE, .value.floatfix.value = (v) } - -#define LWM2M_RESOURCE_FLOATFIX_VAR(id, v) \ - { id, LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE, .value.floatfixvar.var = (v) } - -#define LWM2M_RESOURCE_FLOATFIX_VAR_ARR(id, c, v) \ - { id, LWM2M_RESOURCE_TYPE_FLOATFIX_VARIABLE_ARRAY, .value.floatfixvararr.count = (c), .value.floatfixvararr.var = (v) } - -#define LWM2M_RESOURCE_BOOLEAN(id, v) \ - { id, LWM2M_RESOURCE_TYPE_BOOLEAN_VALUE, .value.boolean.value = (v) } - -#define LWM2M_RESOURCE_BOOLEAN_VAR(id, v) \ - { id, LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE, .value.booleanvar.var = (v) } - -#define LWM2M_RESOURCE_BOOLEAN_VAR_ARR(id, c, v) \ - { id, LWM2M_RESOURCE_TYPE_BOOLEAN_VARIABLE_ARRAY, .value.booleanvararr.count = (c), .value.booleanvararr.var = (v) } - -#define LWM2M_RESOURCE_CALLBACK(id, ...) \ - { id, LWM2M_RESOURCE_TYPE_CALLBACK, .value.callback = __VA_ARGS__ } - -#define LWM2M_INSTANCE(id, resources) \ - { id, sizeof(resources)/sizeof(lwm2m_resource_t), LWM2M_INSTANCE_FLAG_USED, resources } - -#define LWM2M_INSTANCE_UNUSED(id, resources) \ - { id, sizeof(resources)/sizeof(lwm2m_resource_t), 0, resources } - -#define LWM2M_INSTANCES(name, ...) \ - static lwm2m_instance_t name[] = { __VA_ARGS__ } - -#define LWM2M_OBJECT(name, id, instances) \ - static void lwm2m_get_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); \ - static void lwm2m_put_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); \ - static void lwm2m_post_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); \ - static void lwm2m_delete_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); \ - static resource_t rest_rsc_##name = { NULL, NULL, HAS_SUB_RESOURCES | IS_OBSERVABLE, NULL, lwm2m_get_h_##name, lwm2m_post_h_##name, lwm2m_put_h_##name, lwm2m_delete_h_##name, { NULL } }; \ - static const lwm2m_object_t name = { id, sizeof(instances)/sizeof(lwm2m_instance_t), LWM2M_OBJECT_PATH_STR(id), &rest_rsc_##name, instances}; \ - static void lwm2m_get_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { \ - lwm2m_engine_handler(&name, request, response, buffer, preferred_size, offset); } \ - static void lwm2m_put_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { \ - lwm2m_engine_handler(&name, request, response, buffer, preferred_size, offset); } \ - static void lwm2m_post_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { \ - lwm2m_engine_handler(&name, request, response, buffer, preferred_size, offset); } \ - static void lwm2m_delete_h_##name(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { \ - lwm2m_engine_delete_handler(&name, request, response, buffer, preferred_size, offset); } - -/* how do we register attributes in the above resource here ??? */ - -int lwm2m_object_is_resource_string(const lwm2m_resource_t *resource); -int lwm2m_object_is_resource_int(const lwm2m_resource_t *resource); -int lwm2m_object_is_resource_floatfix(const lwm2m_resource_t *resource); -int lwm2m_object_is_resource_boolean(const lwm2m_resource_t *resource); +struct lwm2m_writer { + size_t (* init_write)(lwm2m_context_t *ctx); + size_t (* end_write)(lwm2m_context_t *ctx); + /* For sub-resources */ + size_t (* enter_resource_instance)(lwm2m_context_t *ctx); + size_t (* exit_resource_instance)(lwm2m_context_t *ctx); + size_t (* write_int)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value); + size_t (* write_string)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, const char *value, size_t strlen); + size_t (* write_float32fix)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value, int bits); + size_t (* write_boolean)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int value); + size_t (* write_opaque_header)(lwm2m_context_t *ctx, size_t total_size); +}; + +struct lwm2m_reader { + size_t (* read_int)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value); + size_t (* read_string)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t strlen); + size_t (* read_float32fix)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits); + size_t (* read_boolean)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value); +}; + +typedef lwm2m_status_t +(* lwm2m_write_opaque_callback)(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx, int num_to_write); + +void lwm2m_engine_set_opaque_callback(lwm2m_context_t *ctx, lwm2m_write_opaque_callback cb); + +static inline void +lwm2m_notify_observers(char *path) +{ + coap_notify_observers_sub(NULL, path); +} + +static inline size_t +lwm2m_object_read_int(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value) +{ + return ctx->reader->read_int(ctx, inbuf, len, value); +} + +static inline size_t +lwm2m_object_read_string(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t strlen) +{ + return ctx->reader->read_string(ctx, inbuf, len, value, strlen); +} + +static inline size_t +lwm2m_object_read_float32fix(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits) +{ + return ctx->reader->read_float32fix(ctx, inbuf, len, value, bits); +} + +static inline size_t +lwm2m_object_read_boolean(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value) +{ + return ctx->reader->read_boolean(ctx, inbuf, len, value); +} + +static inline size_t +lwm2m_object_write_int(lwm2m_context_t *ctx, int32_t value) +{ + size_t s; + s = ctx->writer->write_int(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_string(lwm2m_context_t *ctx, const char *value, size_t strlen) +{ + size_t s; + s = ctx->writer->write_string(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value, strlen); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_float32fix(lwm2m_context_t *ctx, int32_t value, int bits) +{ + size_t s; + s = ctx->writer->write_float32fix(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value, bits); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_boolean(lwm2m_context_t *ctx, int value) +{ + size_t s; + s = ctx->writer->write_boolean(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value); + ctx->outbuf->len += s; + return s; +} static inline int -lwm2m_object_is_resource_callback(const lwm2m_resource_t *resource) +lwm2m_object_write_opaque_stream(lwm2m_context_t *ctx, int size, lwm2m_write_opaque_callback cb) { - return resource != NULL && resource->type == LWM2M_RESOURCE_TYPE_CALLBACK; + /* 1. - create a header of either OPAQUE (nothing) or TLV if the format is TLV */ + size_t s; + if(ctx->writer->write_opaque_header != NULL) { + s = ctx->writer->write_opaque_header(ctx, size); + ctx->outbuf->len += s; + } else { + return 0; + } + /* 2. - set the callback so that future data will be grabbed from the callback */ + lwm2m_engine_set_opaque_callback(ctx, cb); + return 1; } -const uint8_t * -lwm2m_object_get_resource_string(const lwm2m_resource_t *resource, - const lwm2m_context_t *context); - -uint16_t -lwm2m_object_get_resource_strlen(const lwm2m_resource_t *resource, - const lwm2m_context_t *context); - -int -lwm2m_object_set_resource_string(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - uint16_t len, const uint8_t *string); - -int -lwm2m_object_get_resource_int(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t *value); - -int -lwm2m_object_set_resource_int(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t value); - -int -lwm2m_object_get_resource_floatfix(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t *value); - -int -lwm2m_object_set_resource_floatfix(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int32_t value); - -int -lwm2m_object_get_resource_boolean(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int *value); - -int -lwm2m_object_set_resource_boolean(const lwm2m_resource_t *resource, - const lwm2m_context_t *context, - int value); - -static inline resource_t * -lwm2m_object_get_coap_resource(const lwm2m_object_t *object) +/* Resource instance functions (_ri)*/ + +static inline size_t +lwm2m_object_write_enter_ri(lwm2m_context_t *ctx) { - return (resource_t *)object->coap_resource; + if(ctx->writer->enter_resource_instance != NULL) { + size_t s; + s = ctx->writer->enter_resource_instance(ctx); + ctx->outbuf->len += s; + return s; + } + return 0; } -static inline void -lwm2m_object_notify_observers(const lwm2m_object_t *object, char *path) +static inline size_t +lwm2m_object_write_exit_ri(lwm2m_context_t *ctx) +{ + if(ctx->writer->exit_resource_instance != NULL) { + size_t s; + s = ctx->writer->exit_resource_instance(ctx); + ctx->outbuf->len += s; + return s; + } + return 0; +} + +static inline size_t +lwm2m_object_write_int_ri(lwm2m_context_t *ctx, uint16_t id, int32_t value) +{ + size_t s; + ctx->resource_instance_id = id; + s = ctx->writer->write_int(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_string_ri(lwm2m_context_t *ctx, uint16_t id, const char *value, size_t strlen) +{ + size_t s; + ctx->resource_instance_id = id; + s = ctx->writer->write_string(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value, strlen); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_float32fix_ri(lwm2m_context_t *ctx, uint16_t id, int32_t value, int bits) +{ + size_t s; + ctx->resource_instance_id = id; + s = ctx->writer->write_float32fix(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value, bits); + ctx->outbuf->len += s; + return s; +} + +static inline size_t +lwm2m_object_write_boolean_ri(lwm2m_context_t *ctx, uint16_t id, int value) +{ + size_t s; + ctx->resource_instance_id = id; + s = ctx->writer->write_boolean(ctx, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len, value); + ctx->outbuf->len += s; + return s; +} + +static inline int +lwm2m_object_is_final_incoming(lwm2m_context_t *ctx) { - coap_notify_observers_sub(lwm2m_object_get_coap_resource(object), path); + uint8_t more; + if(coap_get_header_block1(ctx->request, NULL, &more, NULL, NULL)) { + return !more; + } + /* If we do not know this is final... it might not be... */ + return 0; } #include "lwm2m-engine.h" diff --git a/os/services/lwm2m/lwm2m-plain-text.c b/os/services/lwm2m/lwm2m-plain-text.c index b2bc5dcbed4cd2f9de39aec41302818b0687d1d1..3dc816ddc4ac28881bfa9ebbf0ca64586a396c5f 100644 --- a/os/services/lwm2m/lwm2m-plain-text.c +++ b/os/services/lwm2m/lwm2m-plain-text.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ @@ -47,13 +47,23 @@ #include <stdlib.h> #include <string.h> -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-text" +#define LOG_LEVEL LOG_LEVEL_NONE +/*---------------------------------------------------------------------------*/ +static size_t +init_write(lwm2m_context_t *ctx) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static size_t +end_write(lwm2m_context_t *ctx) +{ + return 0; +} /*---------------------------------------------------------------------------*/ size_t lwm2m_plain_text_read_int(const uint8_t *inbuf, size_t len, int32_t *value) @@ -109,15 +119,16 @@ lwm2m_plain_text_read_float32fix(const uint8_t *inbuf, size_t len, if(frac > 1) { *value += ((counter << bits) / frac); } - PRINTF("READ FLOATFIX: \"%.*s\" => int(%ld) frac(%ld) f=%ld Value=%ld\n", - (int)len, (char *)inbuf, - (long)integerpart, - (long)counter, - (long)frac, - (long)*value); + LOG_DBG("READ FLOATFIX: \"%.*s\" => int(%ld) frac(%ld) f=%ld Value=%ld\n", + (int)len, (char *)inbuf, + (long)integerpart, + (long)counter, + (long)frac, + (long)*value); if(neg) { *value = -*value; } + return i; } /*---------------------------------------------------------------------------*/ @@ -153,7 +164,7 @@ lwm2m_plain_text_write_float32fix(uint8_t *outbuf, size_t outlen, } /*---------------------------------------------------------------------------*/ static size_t -write_boolean(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_boolean(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int value) { if(outlen > 0) { @@ -168,7 +179,7 @@ write_boolean(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, } /*---------------------------------------------------------------------------*/ static size_t -write_int(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_int(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value) { int n = snprintf((char *)outbuf, outlen, "%ld", (long)value); @@ -179,24 +190,30 @@ write_int(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, } /*---------------------------------------------------------------------------*/ static size_t -write_float32fix(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_float32fix(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value, int bits) { return lwm2m_plain_text_write_float32fix(outbuf, outlen, value, bits); } /*---------------------------------------------------------------------------*/ static size_t -write_string(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +write_string(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, const char *value, size_t stringlen) { - int n = snprintf((char *)outbuf, outlen, "%.*s", (int) stringlen, value); - if(n < 0 || n >= outlen) { + int totlen = stringlen; + if(stringlen >= outlen) { return 0; } - return n; + memmove(outbuf, value, totlen); + outbuf[totlen] = 0; + return totlen; } /*---------------------------------------------------------------------------*/ const lwm2m_writer_t lwm2m_plain_text_writer = { + init_write, + end_write, + NULL, /* No support for sub resources here! */ + NULL, write_int, write_string, write_float32fix, @@ -204,14 +221,16 @@ const lwm2m_writer_t lwm2m_plain_text_writer = { }; /*---------------------------------------------------------------------------*/ static size_t -read_int(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_int(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value) { - return lwm2m_plain_text_read_int(inbuf, len, value); + int size = lwm2m_plain_text_read_int(inbuf, len, value); + ctx->last_value_len = size; + return size; } /*---------------------------------------------------------------------------*/ static size_t -read_string(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_string(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t stringlen) { if(stringlen <= len) { @@ -220,23 +239,28 @@ read_string(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, } memcpy(value, inbuf, len); value[len] = '\0'; + ctx->last_value_len = len; return len; } /*---------------------------------------------------------------------------*/ static size_t -read_float32fix(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_float32fix(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits) { - return lwm2m_plain_text_read_float32fix(inbuf, len, value, bits); + int size; + size = lwm2m_plain_text_read_float32fix(inbuf, len, value, bits); + ctx->last_value_len = size; + return size; } /*---------------------------------------------------------------------------*/ static size_t -read_boolean(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_boolean(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value) { if(len > 0) { if(*inbuf == '1' || *inbuf == '0') { *value = *inbuf == '1' ? 1 : 0; + ctx->last_value_len = 1; return 1; } } diff --git a/os/services/lwm2m/lwm2m-plain-text.h b/os/services/lwm2m/lwm2m-plain-text.h index bf12a118ccf031481f5a148c48155117d4f99741..7922a8ce80319476990ff21d4af23dcf7d5e606a 100644 --- a/os/services/lwm2m/lwm2m-plain-text.h +++ b/os/services/lwm2m/lwm2m-plain-text.h @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ */ diff --git a/os/services/lwm2m/lwm2m-rd-client.c b/os/services/lwm2m/lwm2m-rd-client.c new file mode 100644 index 0000000000000000000000000000000000000000..03d21e33e523bc100212af1a5824adb48e5b0cfe --- /dev/null +++ b/os/services/lwm2m/lwm2m-rd-client.c @@ -0,0 +1,738 @@ +/* + * Copyright (c) 2015-2018, Yanzi Networks AB. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \addtogroup lwm2m + * @{ + */ + +/** + * \file + * Implementation of the Contiki OMA LWM2M engine + * Registration and bootstrap client + * \author + * Joakim Eriksson <joakime@sics.se> + * Niclas Finne <nfi@sics.se> + * Joel Hoglund <joel@sics.se> + */ + +#include "lwm2m-engine.h" +#include "lwm2m-object.h" +#include "lwm2m-device.h" +#include "lwm2m-plain-text.h" +#include "lwm2m-json.h" +#include "lwm2m-rd-client.h" +#include "coap.h" +#include "coap-engine.h" +#include "coap-endpoint.h" +#include "coap-callback-api.h" +#include "lwm2m-security.h" +#include <stdio.h> +#include <string.h> +#include <inttypes.h> + +#if UIP_CONF_IPV6_RPL +#include "rpl.h" +#endif /* UIP_CONF_IPV6_RPL */ + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-rd" +#define LOG_LEVEL LOG_LEVEL_LWM2M + +#ifndef LWM2M_DEFAULT_CLIENT_LIFETIME +#define LWM2M_DEFAULT_CLIENT_LIFETIME 30 /* sec */ +#endif + +#define MAX_RD_UPDATE_WAIT 5000 + +#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) +#define BS_REMOTE_PORT UIP_HTONS(5685) + +#define STATE_MACHINE_UPDATE_INTERVAL 500 + +static struct lwm2m_session_info session_info; +static coap_request_state_t rd_request_state; + +static coap_message_t request[1]; /* This way the message can be treated as pointer as usual. */ + +/* The states for the RD client state machine */ +/* When node is unregistered it ends up in UNREGISTERED + and this is going to be there until use X or Y kicks it + back into INIT again */ +#define INIT 0 +#define WAIT_NETWORK 1 +#define DO_BOOTSTRAP 3 +#define BOOTSTRAP_SENT 4 +#define BOOTSTRAP_DONE 5 +#define DO_REGISTRATION 6 +#define REGISTRATION_SENT 7 +#define REGISTRATION_DONE 8 +#define UPDATE_SENT 9 +#define DEREGISTER 10 +#define DEREGISTER_SENT 11 +#define DEREGISTER_FAILED 12 +#define DEREGISTERED 13 + +#define FLAG_RD_DATA_DIRTY 0x01 +#define FLAG_RD_DATA_UPDATE_TRIGGERED 0x02 +#define FLAG_RD_DATA_UPDATE_ON_DIRTY 0x10 + +static uint8_t rd_state = 0; +static uint8_t rd_flags = FLAG_RD_DATA_UPDATE_ON_DIRTY; +static uint64_t wait_until_network_check = 0; +static uint64_t last_update; +static uint64_t last_rd_progress = 0; + +static char query_data[64]; /* allocate some data for queries and updates */ +static uint8_t rd_data[128]; /* allocate some data for the RD */ + +static uint32_t rd_block1; +static uint8_t rd_more; +static coap_timer_t rd_timer; +static void (*rd_callback)(coap_request_state_t *state); + +static coap_timer_t block1_timer; + +static void check_periodic_observations(); +static void update_callback(coap_request_state_t *state); + +static int +set_rd_data(coap_message_t *request) +{ + lwm2m_buffer_t outbuf; + + /* setup the output buffer */ + outbuf.buffer = rd_data; + outbuf.size = sizeof(rd_data); + outbuf.len = 0; + + /* this will also set the request payload */ + rd_more = lwm2m_engine_set_rd_data(&outbuf, 0); + coap_set_payload(request, rd_data, outbuf.len); + + if(rd_more) { + /* set the first block here */ + LOG_DBG("Setting block1 in request\n"); + coap_set_header_block1(request, 0, 1, sizeof(rd_data)); + } + return outbuf.len; +} +/*---------------------------------------------------------------------------*/ +static void +prepare_update(coap_message_t *request, int triggered) { + coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); + coap_set_header_uri_path(request, session_info.assigned_ep); + + snprintf(query_data, sizeof(query_data) - 1, "?lt=%d&b=%s", session_info.lifetime, session_info.binding); + LOG_DBG("UPDATE:%s %s\n", session_info.assigned_ep, query_data); + coap_set_header_uri_query(request, query_data); + + if((triggered || rd_flags & FLAG_RD_DATA_UPDATE_ON_DIRTY) && (rd_flags & FLAG_RD_DATA_DIRTY)) { + rd_flags &= ~FLAG_RD_DATA_DIRTY; + set_rd_data(request); + rd_callback = update_callback; + } +} +/*---------------------------------------------------------------------------*/ +static int +has_network_access(void) +{ +#if UIP_CONF_IPV6_RPL +/* NATIVE PLATFORM is not really running RPL */ +#ifndef CONTIKI_TARGET_NATIVE + if(rpl_get_any_dag() == NULL) { + return 0; + } +#endif +#endif /* UIP_CONF_IPV6_RPL */ + return 1; +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_rd_client_is_registered(void) +{ + return rd_state == REGISTRATION_DONE || rd_state == UPDATE_SENT; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_use_bootstrap_server(int use) +{ + session_info.use_bootstrap = use != 0; + if(session_info.use_bootstrap) { + rd_state = INIT; + } +} +/*---------------------------------------------------------------------------*/ +/* will take another argument when we support multiple sessions */ +void +lwm2m_rd_client_set_session_callback(session_callback_t cb) +{ + session_info.callback = cb; +} +/*---------------------------------------------------------------------------*/ +static void +perform_session_callback(int state) +{ + if(session_info.callback != NULL) { + LOG_DBG("Performing session callback: %d cb:%p\n", + state, session_info.callback); + session_info.callback(&session_info, state); + } +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_use_registration_server(int use) +{ + session_info.use_registration = use != 0; + if(session_info.use_registration) { + rd_state = INIT; + } +} +/*---------------------------------------------------------------------------*/ +uint16_t +lwm2m_rd_client_get_lifetime(void) +{ + return session_info.lifetime; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_set_lifetime(uint16_t lifetime) +{ + if(lifetime > 0) { + session_info.lifetime = lifetime; + } else { + session_info.lifetime = LWM2M_DEFAULT_CLIENT_LIFETIME; + } +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_set_update_rd(void) +{ + rd_flags |= FLAG_RD_DATA_DIRTY; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_set_automatic_update(int update) +{ + rd_flags = (rd_flags & ~FLAG_RD_DATA_UPDATE_ON_DIRTY) | + (update != 0 ? FLAG_RD_DATA_UPDATE_ON_DIRTY : 0); +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_register_with_server(const coap_endpoint_t *server) +{ + coap_endpoint_copy(&session_info.server_ep, server); + session_info.has_registration_server_info = 1; + session_info.registered = 0; + if(session_info.use_registration) { + rd_state = INIT; + } +} +/*---------------------------------------------------------------------------*/ +static int +update_registration_server(void) +{ + if(session_info.has_registration_server_info) { + return 1; + } + +#if UIP_CONF_IPV6_RPL + { + rpl_dag_t *dag; + + /* Use the DAG id as server address if no other has been specified */ + dag = rpl_get_any_dag(); + if(dag != NULL) { + /* create coap-endpoint? */ + /* uip_ipaddr_copy(&server_ipaddr, &dag->dag_id); */ + /* server_port = REMOTE_PORT; */ + return 1; + } + } +#endif /* UIP_CONF_IPV6_RPL */ + + return 0; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_register_with_bootstrap_server(const coap_endpoint_t *server) +{ + coap_endpoint_copy(&session_info.bs_server_ep, server); + session_info.has_bs_server_info = 1; + session_info.bootstrapped = 0; + session_info.registered = 0; + if(session_info.use_bootstrap) { + rd_state = INIT; + } +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_rd_client_deregister(void) +{ + if(lwm2m_rd_client_is_registered()) { + rd_state = DEREGISTER; + return 1; + } + /* Not registered */ + return 0; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_update_triggered(void) +{ + rd_flags |= FLAG_RD_DATA_UPDATE_TRIGGERED; + /* Here we need to do an CoAP timer poll - to get a quick request transmission! */ +} +/*---------------------------------------------------------------------------*/ +static int +update_bootstrap_server(void) +{ + if(session_info.has_bs_server_info) { + return 1; + } + +#if UIP_CONF_IPV6_RPL + { + rpl_dag_t *dag; + + /* Use the DAG id as server address if no other has been specified */ + dag = rpl_get_any_dag(); + if(dag != NULL) { + /* create coap endpoint */ + /* uip_ipaddr_copy(&bs_server_ipaddr, &dag->dag_id); */ + /* bs_server_port = REMOTE_PORT; */ + return 1; + } + } +#endif /* UIP_CONF_IPV6_RPL */ + + return 0; +} +/*---------------------------------------------------------------------------*/ +/* + * A client initiated bootstrap starts with a POST to /bs?ep={session_info.ep}, + * on the bootstrap server. The server should reply with 2.04. + * The server will thereafter do DELETE and or PUT to write new client objects. + * The bootstrap finishes with the server doing POST to /bs on the client. + * + * Page 64 in 07 April 2016 spec. + * + * TODO + */ +static void +bootstrap_callback(coap_request_state_t *state) +{ + LOG_DBG("Bootstrap callback Response: %d, ", state->response != NULL); + if(state->response) { + if(CHANGED_2_04 == state->response->code) { + LOG_DBG_("Considered done!\n"); + rd_state = BOOTSTRAP_DONE; + return; + } + /* Possible error response codes are 4.00 Bad request & 4.15 Unsupported content format */ + LOG_DBG_("Failed with code %d. Retrying\n", state->response->code); + /* TODO Application callback? */ + rd_state = INIT; + } else if(BOOTSTRAP_SENT == rd_state) { /* this can handle double invocations */ + /* Failure! */ + LOG_DBG("Bootstrap failed! Retry?"); + rd_state = DO_BOOTSTRAP; + } else { + LOG_DBG("Ignore\n"); + } +} +/*---------------------------------------------------------------------------*/ +static void +produce_more_rd(void) +{ + lwm2m_buffer_t outbuf; + + LOG_DBG("GOT Continue!\n"); + + /* setup the output buffer */ + outbuf.buffer = rd_data; + outbuf.size = sizeof(rd_data); + outbuf.len = 0; + + rd_block1++; + + /* this will also set the request payload */ + rd_more = lwm2m_engine_set_rd_data(&outbuf, rd_block1); + coap_set_payload(request, rd_data, outbuf.len); + + LOG_DBG("Setting block1 in request - block: %d more: %d\n", + (int)rd_block1, (int)rd_more); + coap_set_header_block1(request, rd_block1, rd_more, sizeof(rd_data)); + + coap_send_request(&rd_request_state, &session_info.server_ep, request, rd_callback); +} +/*---------------------------------------------------------------------------*/ +static void +block1_rd_callback(coap_timer_t *timer) +{ + produce_more_rd(); +} +/*---------------------------------------------------------------------------*/ +/* + * Page 65-66 in 07 April 2016 spec. + */ +static void +registration_callback(coap_request_state_t *state) +{ + LOG_DBG("Registration callback. Response: %d, ", state->response != NULL); + if(state->response) { + /* check state and possibly set registration to done */ + /* If we get a continue - we need to call the rd generator one more time */ + if(CONTINUE_2_31 == state->response->code) { + /* We assume that size never change?! */ + coap_get_header_block1(state->response, &rd_block1, NULL, NULL, NULL); + coap_timer_set_callback(&block1_timer, block1_rd_callback); + coap_timer_set(&block1_timer, 1); /* delay 1 ms */ + LOG_DBG_("Continue\n"); + } else if(CREATED_2_01 == state->response->code) { + if(state->response->location_path_len < LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN) { + memcpy(session_info.assigned_ep, state->response->location_path, + state->response->location_path_len); + session_info.assigned_ep[state->response->location_path_len] = 0; + /* if we decide to not pass the lt-argument on registration, we should force an initial "update" to register lifetime with server */ + rd_state = REGISTRATION_DONE; + /* remember the last reg time */ + last_update = coap_timer_uptime(); + LOG_DBG_("Done (assigned EP='%s')!\n", session_info.assigned_ep); + perform_session_callback(LWM2M_RD_CLIENT_REGISTERED); + return; + } + + LOG_DBG_("failed to handle assigned EP: '"); + LOG_DBG_COAP_STRING(state->response->location_path, + state->response->location_path_len); + LOG_DBG_("'. Re-init network.\n"); + } else { + /* Possible error response codes are 4.00 Bad request & 4.03 Forbidden */ + LOG_DBG_("failed with code %d. Re-init network\n", state->response->code); + } + /* TODO Application callback? */ + rd_state = INIT; + /* remember last progress time */ + last_rd_progress = coap_timer_uptime(); + } else { + LOG_DBG_("Ignore\n"); + } +} +/*---------------------------------------------------------------------------*/ +/* + * Page 65-66 in 07 April 2016 spec. + */ +static void +update_callback(coap_request_state_t *state) +{ + LOG_DBG("Update callback. Response: %d, ", state->response != NULL); + + if(state->response) { + /* If we get a continue - we need to call the rd generator one more time */ + if(CONTINUE_2_31 == state->response->code) { + /* We assume that size never change?! */ + LOG_DBG_("Continue\n"); + coap_get_header_block1(state->response, &rd_block1, NULL, NULL, NULL); + coap_timer_set_callback(&block1_timer, block1_rd_callback); + coap_timer_set(&block1_timer, 1); /* delay 1 ms */ + } else if(CHANGED_2_04 == state->response->code) { + LOG_DBG_("Done!\n"); + /* remember the last reg time */ + last_update = coap_timer_uptime(); + rd_state = REGISTRATION_DONE; + rd_flags &= ~FLAG_RD_DATA_UPDATE_TRIGGERED; + } else { + /* Possible error response codes are 4.00 Bad request & 4.04 Not Found */ + LOG_DBG_("Failed with code %d. Retrying registration\n", + state->response->code); + rd_state = DO_REGISTRATION; + } + /* remember last progress */ + last_rd_progress = coap_timer_uptime(); + } else { + LOG_DBG("Ignore\n"); + } +} +/*---------------------------------------------------------------------------*/ +static void +deregister_callback(coap_request_state_t *state) +{ + LOG_DBG("Deregister callback. Response Code: %d\n", + state->response != NULL ? state->response->code : 0); + + if(state->response && (DELETED_2_02 == state->response->code)) { + LOG_DBG("Deregistration success\n"); + rd_state = DEREGISTERED; + perform_session_callback(LWM2M_RD_CLIENT_DEREGISTERED); + } else { + LOG_DBG("Deregistration failed\n"); + if(rd_state == DEREGISTER_SENT) { + rd_state = DEREGISTER_FAILED; + perform_session_callback(LWM2M_RD_CLIENT_DEREGISTER_FAILED); + } + } +} +/*---------------------------------------------------------------------------*/ +static void +recover_from_rd_delay(void) +{ + /* This can be improved in the future... */ + rd_state = INIT; +} +/*---------------------------------------------------------------------------*/ +/* CoAP timer callback */ +static void +periodic_process(coap_timer_t *timer) +{ + uint64_t now; + + /* reschedule the CoAP timer */ + coap_timer_reset(&rd_timer, STATE_MACHINE_UPDATE_INTERVAL); + now = coap_timer_uptime(); + + LOG_DBG("RD Client - state: %d, ms: %lu\n", rd_state, + (unsigned long)coap_timer_uptime()); + + switch(rd_state) { + case INIT: + LOG_DBG("RD Client started with endpoint '%s' and client lifetime %d\n", session_info.ep, session_info.lifetime); + rd_state = WAIT_NETWORK; + break; + case WAIT_NETWORK: + if(now > wait_until_network_check) { + /* check each 10 seconds before next check */ + LOG_DBG("Checking for network... %lu\n", + (unsigned long)wait_until_network_check); + wait_until_network_check = now + 10000; + if(has_network_access()) { + /* Either do bootstrap then registration */ + if(session_info.use_bootstrap) { + rd_state = DO_BOOTSTRAP; + } else { + rd_state = DO_REGISTRATION; + } + } + /* Otherwise wait until for a network to join */ + } + break; + case DO_BOOTSTRAP: + if(session_info.use_bootstrap && session_info.bootstrapped == 0) { + if(update_bootstrap_server()) { + /* prepare request, TID is set by COAP_BLOCKING_REQUEST() */ + coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); + coap_set_header_uri_path(request, "/bs"); + + snprintf(query_data, sizeof(query_data) - 1, "?ep=%s", session_info.ep); + coap_set_header_uri_query(request, query_data); + LOG_INFO("Registering ID with bootstrap server ["); + LOG_INFO_COAP_EP(&session_info.bs_server_ep); + LOG_INFO_("] as '%s'\n", query_data); + + coap_send_request(&rd_request_state, &session_info.bs_server_ep, + request, bootstrap_callback); + + rd_state = BOOTSTRAP_SENT; + } + } + break; + case BOOTSTRAP_SENT: + /* Just wait for bootstrap to be done... */ + break; + case BOOTSTRAP_DONE: + /* check that we should still use bootstrap */ + if(session_info.use_bootstrap) { + lwm2m_security_server_t *security; + LOG_DBG("*** Bootstrap - checking for server info...\n"); + /* get the security object - ignore bootstrap servers */ + for(security = lwm2m_security_get_first(); + security != NULL; + security = lwm2m_security_get_next(security)) { + if(security->bootstrap == 0) { + break; + } + } + + if(security != NULL) { + /* get the server URI */ + if(security->server_uri_len > 0) { + uint8_t secure = 0; + + LOG_DBG("**** Found security instance using: "); + LOG_DBG_COAP_STRING((const char *)security->server_uri, + security->server_uri_len); + LOG_DBG_(" (len %d) \n", security->server_uri_len); + /* TODO Should verify it is a URI */ + /* Check if secure */ + secure = strncmp((const char *)security->server_uri, + "coaps:", 6) == 0; + + if(!coap_endpoint_parse((const char *)security->server_uri, + security->server_uri_len, + &session_info.server_ep)) { + LOG_DBG("Failed to parse server URI!\n"); + } else { + LOG_DBG("Server address:"); + LOG_DBG_COAP_EP(&session_info.server_ep); + LOG_DBG_("\n"); + if(secure) { + LOG_DBG("Secure CoAP requested but not supported - can not bootstrap\n"); + } else { + lwm2m_rd_client_register_with_server(&session_info.server_ep); + session_info.bootstrapped++; + } + } + } else { + LOG_DBG("** failed to parse URI "); + LOG_DBG_COAP_STRING((const char *)security->server_uri, + security->server_uri_len); + LOG_DBG_("\n"); + } + } + + /* if we did not register above - then fail this and restart... */ + if(session_info.bootstrapped == 0) { + /* Not ready. Lets retry with the bootstrap server again */ + rd_state = DO_BOOTSTRAP; + } else { + rd_state = DO_REGISTRATION; + } + } + break; + case DO_REGISTRATION: + if(!coap_endpoint_is_connected(&session_info.server_ep)) { + /* Not connected... wait a bit... and retry connection */ + coap_endpoint_connect(&session_info.server_ep); + LOG_DBG("Wait until connected... \n"); + return; + } + if(session_info.use_registration && !session_info.registered && + update_registration_server()) { + int len; + + /* prepare request, TID was set by COAP_BLOCKING_REQUEST() */ + coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0); + coap_set_header_uri_path(request, "/rd"); + + snprintf(query_data, sizeof(query_data) - 1, "?ep=%s<=%d&b=%s", session_info.ep, session_info.lifetime, session_info.binding); + coap_set_header_uri_query(request, query_data); + + len = set_rd_data(request); + rd_callback = registration_callback; + + LOG_INFO("Registering with ["); + LOG_INFO_COAP_EP(&session_info.server_ep); + LOG_INFO_("] lwm2m endpoint '%s': '", query_data); + if(len) { + LOG_INFO_COAP_STRING((const char *)rd_data, len); + } + LOG_INFO_("' More:%d\n", rd_more); + + coap_send_request(&rd_request_state, &session_info.server_ep, + request, registration_callback); + last_rd_progress = coap_timer_uptime(); + rd_state = REGISTRATION_SENT; + } + break; + case REGISTRATION_SENT: + /* just wait until the callback kicks us to the next state... */ + if(last_rd_progress + MAX_RD_UPDATE_WAIT < coap_timer_uptime()) { + /* Timeout on the update - something is wrong? */ + recover_from_rd_delay(); + } + break; + case REGISTRATION_DONE: + /* All is done! */ + + check_periodic_observations(); /* TODO: manage periodic observations */ + + /* check if it is time for the next update */ + if((rd_flags & FLAG_RD_DATA_UPDATE_TRIGGERED) || + ((uint32_t)session_info.lifetime * 500) <= now - last_update) { + /* triggered or time to send an update to the server, at half-time! sec vs ms */ + prepare_update(request, rd_flags & FLAG_RD_DATA_UPDATE_TRIGGERED); + coap_send_request(&rd_request_state, &session_info.server_ep, request, + update_callback); + last_rd_progress = coap_timer_uptime(); + rd_state = UPDATE_SENT; + } + break; + + case UPDATE_SENT: + /* just wait until the callback kicks us to the next state... */ + if(last_rd_progress + MAX_RD_UPDATE_WAIT < coap_timer_uptime()) { + /* Timeout on the update - something is wrong? */ + recover_from_rd_delay(); + } + break; + case DEREGISTER: + LOG_INFO("DEREGISTER %s\n", session_info.assigned_ep); + coap_init_message(request, COAP_TYPE_CON, COAP_DELETE, 0); + coap_set_header_uri_path(request, session_info.assigned_ep); + coap_send_request(&rd_request_state, &session_info.server_ep, request, + deregister_callback); + rd_state = DEREGISTER_SENT; + break; + case DEREGISTER_SENT: + break; + case DEREGISTER_FAILED: + break; + case DEREGISTERED: + break; + + default: + LOG_WARN("Unhandled state: %d\n", rd_state); + } +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_rd_client_init(const char *ep) +{ + session_info.ep = ep; + /* default binding U = UDP, UQ = UDP Q-mode*/ + session_info.binding = "U"; + if(session_info.lifetime == 0) { + session_info.lifetime = LWM2M_DEFAULT_CLIENT_LIFETIME; + } + rd_state = INIT; + + /* call the RD client periodically */ + coap_timer_set_callback(&rd_timer, periodic_process); + coap_timer_set(&rd_timer, STATE_MACHINE_UPDATE_INTERVAL); +} +/*---------------------------------------------------------------------------*/ +static void +check_periodic_observations(void) +{ +/* TODO */ +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-rd-client.h b/os/services/lwm2m/lwm2m-rd-client.h new file mode 100644 index 0000000000000000000000000000000000000000..7fba7e0ae813acfff2f6a5c6e6bf81c48c09b2a2 --- /dev/null +++ b/os/services/lwm2m/lwm2m-rd-client.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016-2018, SICS Swedish ICT AB. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \addtogroup lwm2m + * @{ + */ + +/** + * \file + * Header file for the Contiki OMA LWM2M Registration and Bootstrap + * Client. + * \author + * Joakim Eriksson <joakime@sics.se> + * Niclas Finne <nfi@sics.se> + */ + +#ifndef LWM2M_RD_CLIENT_H_ +#define LWM2M_RD_CLIENT_H_ + +#define LWM2M_RD_CLIENT_BOOTSTRAPPED 1 +#define LWM2M_RD_CLIENT_REGISTERED 2 +#define LWM2M_RD_CLIENT_DEREGISTERED 3 +#define LWM2M_RD_CLIENT_DEREGISTER_FAILED 4 +#define LWM2M_RD_CLIENT_DISCONNECTED 5 + +#include "lwm2m-object.h" + +struct lwm2m_session_info; +typedef void (*session_callback_t)(struct lwm2m_session_info *session, int status); + +int lwm2m_rd_client_is_registered(void); +void lwm2m_rd_client_use_bootstrap_server(int use); +void lwm2m_rd_client_use_registration_server(int use); +void lwm2m_rd_client_register_with_server(const coap_endpoint_t *server); +void lwm2m_rd_client_register_with_bootstrap_server(const coap_endpoint_t *server); +uint16_t lwm2m_rd_client_get_lifetime(void); +void lwm2m_rd_client_set_lifetime(uint16_t lifetime); +/* Indicate that something in the object list have changed */ +void lwm2m_rd_client_set_update_rd(void); +/* Control if the object list should be automatically updated at updates of lifetime */ +void lwm2m_rd_client_set_automatic_update(int update); +/* trigger an immediate update */ +void lwm2m_rd_client_update_triggered(void); + +int lwm2m_rd_client_deregister(void); +void lwm2m_rd_client_init(const char *ep); + +void lwm2m_rd_client_set_session_callback(session_callback_t cb); + +#ifndef LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN +#define LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN 15 +#endif /* LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN */ + +/*---------------------------------------------------------------------------*/ +/*- Server session-*Currently single session only*---------------------------*/ +/*---------------------------------------------------------------------------*/ +struct lwm2m_session_info { + const char *ep; + const char *binding; + char assigned_ep[LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN]; + uint16_t lifetime; + coap_endpoint_t bs_server_ep; + coap_endpoint_t server_ep; + uint8_t use_bootstrap; + uint8_t has_bs_server_info; + uint8_t use_registration; + uint8_t has_registration_server_info; + uint8_t registered; + uint8_t bootstrapped; /* bootstrap done */ + session_callback_t callback; +}; + +#endif /* LWM2M_RD_CLIENT_H_ */ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-security.c b/os/services/lwm2m/lwm2m-security.c index 953279b4d2a1eb4b9b05da445670ea35d42e5b80..e4275f280f53206151ee3e9b1e364031e2faee96 100644 --- a/os/services/lwm2m/lwm2m-security.c +++ b/os/services/lwm2m/lwm2m-security.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ * */ @@ -43,70 +43,411 @@ */ #include <stdint.h> +#include <string.h> +#include <inttypes.h> #include "lwm2m-object.h" #include "lwm2m-engine.h" +#include "lwm2m-server.h" +#include "lwm2m-security.h" +#include "coap-keystore.h" +#include "lib/list.h" + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-sec" +#define LOG_LEVEL LOG_LEVEL_LWM2M + +#define MAX_COUNT LWM2M_SERVER_MAX_COUNT + +static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx); + +static lwm2m_object_instance_t *get_by_id(uint16_t instance_id, + lwm2m_status_t *status); + +static const lwm2m_resource_id_t resources[] = { + LWM2M_SECURITY_SERVER_URI_ID, LWM2M_SECURITY_BOOTSTRAP_SERVER_ID, + LWM2M_SECURITY_MODE_ID, LWM2M_SECURITY_CLIENT_PKI_ID, + LWM2M_SECURITY_SERVER_PKI_ID, LWM2M_SECURITY_KEY_ID, + LWM2M_SECURITY_SHORT_SERVER_ID +}; + +LIST(instances_list); +static lwm2m_security_server_t instances[MAX_COUNT]; +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +create_instance(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + int i; + + instance = get_by_id(instance_id, NULL); + if(instance != NULL) { + /* An instance with this id is already registered */ + if(status) { + *status = LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + return NULL; + } + + for(i = 0; i < MAX_COUNT; i++) { + if(instances[i].instance.instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + memset(&instances[i], 0, sizeof(instances[i])); + instances[i].instance.callback = lwm2m_callback; + instances[i].instance.object_id = LWM2M_OBJECT_SECURITY_ID; + instances[i].instance.instance_id = instance_id; + instances[i].instance.resource_ids = resources; + instances[i].instance.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + list_add(instances_list, &instances[i].instance); + + LOG_DBG("Create new security instance %u\n", instance_id); + return &instances[i].instance; + } + } + + if(status) { + *status = LWM2M_STATUS_SERVICE_UNAVAILABLE; + } + + return NULL; +} +/*---------------------------------------------------------------------------*/ +static int +delete_instance(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + + if(instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + /* Remove all instances */ + while((instance = list_pop(instances_list)) != NULL) { + instance->instance_id = LWM2M_OBJECT_INSTANCE_NONE; + } + return 1; + } + + instance = get_by_id(instance_id, NULL); + if(instance != NULL) { + instance->instance_id = LWM2M_OBJECT_INSTANCE_NONE; + list_remove(instances_list, instance); + return 1; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_first(lwm2m_status_t *status) +{ + return list_head(instances_list); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_next(lwm2m_object_instance_t *instance, lwm2m_status_t *status) +{ + return instance == NULL ? NULL : instance->next; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_by_id(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + for(instance = list_head(instances_list); + instance != NULL; + instance = instance->next) { + if(instance->instance_id == instance_id) { + return instance; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) +{ + /* NOTE: the create operation will only create an instance and should + avoid reading out data */ + int32_t value; + int iv; + lwm2m_security_server_t *security; + security = (lwm2m_security_server_t *) object; + + if(ctx->operation == LWM2M_OP_WRITE) { + /* Handle the writes */ + switch(ctx->resource_id) { + case LWM2M_SECURITY_SERVER_URI_ID: + LOG_DBG("Writing security URI value: len: %"PRId16"\n", ctx->inbuf->size); + value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->server_uri, LWM2M_SECURITY_URI_SIZE); + /* This is string... */ + security->server_uri_len = ctx->last_value_len; + break; + case LWM2M_SECURITY_BOOTSTRAP_SERVER_ID: + value = lwm2m_object_read_boolean(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &iv); + if(value > 0) { + LOG_DBG("Set Bootstrap: %d\n", iv); + security->bootstrap = (uint8_t) iv; + } else { + LOG_WARN("Failed to set bootstrap\n"); + } + break; + case LWM2M_SECURITY_MODE_ID: + { + int32_t v2; + value = lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v2); + LOG_DBG("Writing security MODE value: %"PRId32" len: %d\n", v2, + (int)ctx->inbuf->size); + security->security_mode = v2; + } + break; + case LWM2M_SECURITY_CLIENT_PKI_ID: + value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->public_key, LWM2M_SECURITY_KEY_SIZE); + security->public_key_len = ctx->last_value_len; + + LOG_DBG("Writing client PKI: len: %"PRIu16" '", ctx->last_value_len); + LOG_DBG_COAP_STRING((const char *)security->public_key, + ctx->last_value_len); + LOG_DBG_("'\n"); + break; + case LWM2M_SECURITY_KEY_ID: + value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->secret_key, LWM2M_SECURITY_KEY_SIZE); + security->secret_key_len = ctx->last_value_len; + + LOG_DBG("Writing secret key: len: %"PRIu16" '", ctx->last_value_len); + LOG_DBG_COAP_STRING((const char *)security->secret_key, + ctx->last_value_len); + LOG_DBG_("'\n"); + + break; + } + } else if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case LWM2M_SECURITY_SERVER_URI_ID: + lwm2m_object_write_string(ctx, (const char *) security->server_uri, + security->server_uri_len); + break; + default: + return LWM2M_STATUS_ERROR; + } + } + return LWM2M_STATUS_OK; +} -#define DEBUG 0 -#if DEBUG -#include <stdio.h> -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif - -#ifdef LWM2M_CONF_SERVER_MAX_COUNT -#define MAX_COUNT LWM2M_CONF_SERVER_MAX_COUNT -#else -#define MAX_COUNT 2 -#endif - -/* hoping that we do not get more than 64 bytes... */ -#define MAX_SIZE 64 - -static int32_t bs_arr[MAX_COUNT]; -static int32_t secmode_arr[MAX_COUNT]; -static int32_t sid_arr[MAX_COUNT]; - -static char server_uri[MAX_COUNT][MAX_SIZE]; -static uint16_t su_len[MAX_COUNT]; -static char client_id[MAX_COUNT][MAX_SIZE]; -static uint16_t client_id_len[MAX_COUNT]; -static char server_id[MAX_COUNT][MAX_SIZE]; -static uint16_t server_id_len[MAX_COUNT]; -static char psk_key[MAX_COUNT][MAX_SIZE]; -static uint16_t psk_key_len[MAX_COUNT]; -static lwm2m_instance_t security_instances[MAX_COUNT]; - -LWM2M_RESOURCES(security_resources, - LWM2M_RESOURCE_STRING_VAR_ARR(0, MAX_COUNT, MAX_SIZE, su_len, server_uri), - LWM2M_RESOURCE_INTEGER_VAR_ARR(1, MAX_COUNT, bs_arr), - LWM2M_RESOURCE_INTEGER_VAR_ARR(2, MAX_COUNT, secmode_arr), - LWM2M_RESOURCE_STRING_VAR_ARR(3, MAX_COUNT, MAX_SIZE, client_id_len, client_id), - LWM2M_RESOURCE_STRING_VAR_ARR(4, MAX_COUNT, MAX_SIZE, server_id_len, server_id), - /* TODO This should not be readable! */ - LWM2M_RESOURCE_STRING_VAR_ARR(5, MAX_COUNT, MAX_SIZE, psk_key_len, psk_key), - LWM2M_RESOURCE_INTEGER_VAR_ARR(10, MAX_COUNT, sid_arr) - ); -LWM2M_OBJECT(security, 0, security_instances); +/*---------------------------------------------------------------------------*/ +lwm2m_security_server_t * +lwm2m_security_get_first(void) +{ + return list_head(instances_list); +} +/*---------------------------------------------------------------------------*/ +lwm2m_security_server_t * +lwm2m_security_get_next(lwm2m_security_server_t *last) +{ + return last == NULL ? NULL : (lwm2m_security_server_t *)last->instance.next; +} +/*---------------------------------------------------------------------------*/ +lwm2m_security_server_t * +lwm2m_security_add_server(uint16_t instance_id, + uint16_t server_id, + const uint8_t *server_uri, + uint8_t server_uri_len) +{ + lwm2m_security_server_t *server; + int i; + + if(server_uri_len > LWM2M_SECURITY_URI_SIZE) { + LOG_WARN("too long server URI: %u\n", server_uri_len); + return NULL; + } + + for(server = lwm2m_security_get_first(); + server != NULL; + server = lwm2m_security_get_next(server)) { + if(server->server_id == server_id) { + if(server->instance.instance_id != instance_id) { + LOG_WARN("wrong instance id\n"); + return NULL; + } + /* Correct server id and instance id */ + break; + } else if(server->instance.instance_id == instance_id) { + LOG_WARN("wrong server id\n"); + return NULL; + } + } + + if(server == NULL) { + for(i = 0; i < MAX_COUNT; i++) { + if(instances[i].instance.instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + memset(&instances[i], 0, sizeof(instances[i])); + instances[i].instance.callback = lwm2m_callback; + instances[i].instance.object_id = LWM2M_OBJECT_SECURITY_ID; + instances[i].instance.instance_id = instance_id; + instances[i].instance.resource_ids = resources; + instances[i].instance.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + list_add(instances_list, &instances[i].instance); + server = &instances[i]; + } + } + if(server == NULL) { + LOG_WARN("no space for more servers\n"); + return NULL; + } + } + + memcpy(server->server_uri, server_uri, server_uri_len); + server->server_uri_len = server_uri_len; + + return server; +} +/*---------------------------------------------------------------------------*/ +int +lwm2m_security_set_server_psk(lwm2m_security_server_t *server, + const uint8_t *identity, + uint8_t identity_len, + const uint8_t *key, + uint8_t key_len) +{ + if(server == NULL || identity == NULL || key == NULL) { + return 0; + } + if(identity_len > LWM2M_SECURITY_KEY_SIZE) { + LOG_WARN("too large identity: %u\n", identity_len); + return 0; + } + if(key_len > LWM2M_SECURITY_KEY_SIZE) { + LOG_WARN("too large identity: %u\n", key_len); + return 0; + } + memcpy(server->public_key, identity, identity_len); + server->public_key_len = identity_len; + memcpy(server->secret_key, key, key_len); + server->secret_key_len = key_len; + + server->security_mode = LWM2M_SECURITY_MODE_PSK; + + return 1; +} +/*---------------------------------------------------------------------------*/ +static const lwm2m_object_impl_t impl = { + .object_id = LWM2M_OBJECT_SECURITY_ID, + .get_first = get_first, + .get_next = get_next, + .get_by_id = get_by_id, + .create_instance = create_instance, + .delete_instance = delete_instance, +}; +static lwm2m_object_t reg_object = { + .impl = &impl, +}; +/*---------------------------------------------------------------------------*/ +#ifdef WITH_DTLS +#if COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M +static int +get_psk_info(const coap_endpoint_t *address_info, + coap_keystore_psk_entry_t *info) +{ + /* Find matching security object based on address */ + lwm2m_security_server_t *e; + coap_endpoint_t ep; + + if(info == NULL || address_info == NULL) { + return 0; + } + + for(e = lwm2m_security_get_first(); + e != NULL; + e = lwm2m_security_get_next(e)) { + if(e->server_uri_len == 0) { + continue; + } + if(e->security_mode != LWM2M_SECURITY_MODE_PSK) { + /* Only PSK supported for now */ + continue; + } + if(!coap_endpoint_parse((char *)e->server_uri, e->server_uri_len, &ep)) { + /* Failed to parse URI to endpoint */ + LOG_DBG("failed to parse server URI "); + LOG_DBG_COAP_STRING((char *)e->server_uri, e->server_uri_len); + LOG_DBG_("\n"); + continue; + } + if(!coap_endpoint_cmp(address_info, &ep)) { + /* Wrong server */ + LOG_DBG("wrong server "); + LOG_DBG_COAP_EP(address_info); + LOG_DBG_(" != "); + LOG_DBG_COAP_EP(&ep); + LOG_DBG_("\n"); + continue; + } + if(info->identity_len > 0 && info->identity != NULL) { + /* Searching for a specific identity */ + if(info->identity_len != e->public_key_len || + memcmp(info->identity, e->public_key, info->identity_len)) { + /* Identity not matching */ + LOG_DBG("identity not matching\n"); + continue; + } + } + /* Found security information for this server */ + LOG_DBG("found security match!\n"); + break; + } + + if(e == NULL) { + /* No matching security object found */ + return 0; + } + + if(info->identity == NULL || info->identity_len == 0) { + /* Identity requested */ + info->identity = e->public_key; + info->identity_len = e->public_key_len; + return 1; + } + + if(e->secret_key_len == 0) { + /* No secret key / password */ + return 0; + } + + info->key = e->secret_key; + info->key_len = e->secret_key_len; + return 1; +} +static const coap_keystore_t key_store = { + .coap_get_psk_info = get_psk_info +}; +#endif /* COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M */ +#endif /* WITH_DTLS */ /*---------------------------------------------------------------------------*/ void lwm2m_security_init(void) { - lwm2m_instance_t template = LWM2M_INSTANCE_UNUSED(0, security_resources); int i; - /* Initialize the instances */ + LOG_INFO("init\n"); + + list_init(instances_list); + for(i = 0; i < MAX_COUNT; i++) { - security_instances[i] = template; - security_instances[i].id = i; + instances[i].instance.instance_id = LWM2M_OBJECT_INSTANCE_NONE; } + if(lwm2m_engine_add_generic_object(®_object)) { - /** - * Register this device and its handlers - the handlers - * automatically sends in the object to handle. - */ - PRINTF("*** Init lwm2m-security\n"); - lwm2m_engine_register_object(&security); +#ifdef WITH_DTLS +#if COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M + /* Security object handler added - register keystore */ + coap_set_keystore(&key_store); + LOG_DBG("registered keystore\n"); +#endif /* COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M */ +#endif /* WITH_DTLS */ + + } else { + LOG_WARN("failed to register\n"); + } } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/lwm2m-security.h b/os/services/lwm2m/lwm2m-security.h new file mode 100644 index 0000000000000000000000000000000000000000..9fb3df78fc7fb10d95079865d5409ce112571481 --- /dev/null +++ b/os/services/lwm2m/lwm2m-security.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017, SICS Swedish ICT + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \addtogroup lwm2m + * @{ + * + */ +#ifndef LWM2M_SECURITY_H +#define LWM2M_SECURITY_H + +#define LWM2M_SECURITY_SERVER_URI_ID 0 +#define LWM2M_SECURITY_BOOTSTRAP_SERVER_ID 1 +#define LWM2M_SECURITY_MODE_ID 2 +#define LWM2M_SECURITY_CLIENT_PKI_ID 3 +#define LWM2M_SECURITY_SERVER_PKI_ID 4 +#define LWM2M_SECURITY_KEY_ID 5 +#define LWM2M_SECURITY_SHORT_SERVER_ID 10 + +/* Pre-shared key mode */ +#define LWM2M_SECURITY_MODE_PSK 0 +/* Raw Public Key mode */ +#define LWM2M_SECURITY_MODE_RPK 1 +/* Certificate mode */ +#define LWM2M_SECURITY_MODE_CERTIFICATE 2 +/* NoSec mode */ +#define LWM2M_SECURITY_MODE_NOSEC 3 + +#ifdef LWM2M_SECURITY_CONF_URI_SIZE +#define LWM2M_SECURITY_URI_SIZE LWM2M_SECURITY_CONF_URI_SIZE +#else /* LWM2M_SECURITY_CONF_URI_SIZE */ +#define LWM2M_SECURITY_URI_SIZE 64 +#endif /* LWM2M_SECURITY_CONF_URI_SIZE */ + +#ifdef LWM2M_SECURITY_CONF_KEY_SIZE +#define LWM2M_SECURITY_KEY_SIZE LWM2M_SECURITY_CONF_KEY_SIZE +#else /* LWM2M_SECURITY_CONF_KEY_SIZE */ +#define LWM2M_SECURITY_KEY_SIZE 32 +#endif /* LWM2M_SECURITY_CONF_KEY_SIZE */ + +typedef struct { + lwm2m_object_instance_t instance; + uint16_t server_id; + uint8_t bootstrap; + uint8_t security_mode; + uint8_t server_uri[LWM2M_SECURITY_URI_SIZE]; + uint8_t server_uri_len; + uint8_t public_key[LWM2M_SECURITY_KEY_SIZE]; + uint8_t public_key_len; + uint8_t secret_key[LWM2M_SECURITY_KEY_SIZE]; + uint8_t secret_key_len; + uint8_t server_public_key[LWM2M_SECURITY_KEY_SIZE]; + uint8_t server_public_key_len; +} lwm2m_security_server_t; + +lwm2m_security_server_t *lwm2m_security_get_first(void); +lwm2m_security_server_t *lwm2m_security_get_next(lwm2m_security_server_t *last); + +lwm2m_security_server_t *lwm2m_security_add_server(uint16_t instance_id, + uint16_t server_id, + const uint8_t *server_uri, + uint8_t server_uri_len); + +int lwm2m_security_set_server_psk(lwm2m_security_server_t *server, + const uint8_t *identity, + uint8_t identity_len, + const uint8_t *key, + uint8_t key_len); + +void lwm2m_security_init(void); + +#endif /* LWM2M_SECURITY_H */ +/** @} */ diff --git a/os/services/lwm2m/lwm2m-server.c b/os/services/lwm2m/lwm2m-server.c index 9de678682a774475d82b1aed0540b2a0b4e12208..bf0398b4f7e17f4bccad68cb6b4c2c6e72933653 100644 --- a/os/services/lwm2m/lwm2m-server.c +++ b/os/services/lwm2m/lwm2m-server.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ * */ @@ -43,51 +43,253 @@ */ #include <stdint.h> +#include "lib/list.h" #include "lwm2m-object.h" #include "lwm2m-engine.h" +#include "lwm2m-server.h" +#include "lwm2m-rd-client.h" -#define DEBUG 0 -#if DEBUG -#include <stdio.h> -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif - -#ifdef LWM2M_CONF_SERVER_MAX_COUNT -#define MAX_COUNT LWM2M_CONF_SERVER_MAX_COUNT -#else -#define MAX_COUNT 2 -#endif - -static int32_t sid_arr[MAX_COUNT]; -static int32_t lifetime_arr[MAX_COUNT]; -static lwm2m_instance_t server_instances[MAX_COUNT]; - -LWM2M_RESOURCES(server_resources, - LWM2M_RESOURCE_INTEGER_VAR_ARR(0, MAX_COUNT, sid_arr), - LWM2M_RESOURCE_INTEGER_VAR_ARR(1, MAX_COUNT, lifetime_arr), - ); -LWM2M_OBJECT(server, 1, server_instances); +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-srv" +#define LOG_LEVEL LOG_LEVEL_LWM2M + +#define MAX_COUNT LWM2M_SERVER_MAX_COUNT + +static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx); + +static lwm2m_object_instance_t *create_instance(uint16_t instance_id, + lwm2m_status_t *status); +static int delete_instance(uint16_t instance_id, lwm2m_status_t *status); +static lwm2m_object_instance_t *get_first(lwm2m_status_t *status); +static lwm2m_object_instance_t *get_next(lwm2m_object_instance_t *instance, + lwm2m_status_t *status); +static lwm2m_object_instance_t *get_by_id(uint16_t instance_id, + lwm2m_status_t *status); + +static const lwm2m_resource_id_t resources[] = { + RO(LWM2M_SERVER_SHORT_SERVER_ID), + RW(LWM2M_SERVER_LIFETIME_ID), + EX(LWM2M_SERVER_REG_UPDATE_TRIGGER_ID) +}; + +static const lwm2m_object_impl_t impl = { + .object_id = LWM2M_OBJECT_SERVER_ID, + .get_first = get_first, + .get_next = get_next, + .get_by_id = get_by_id, + .create_instance = create_instance, + .delete_instance = delete_instance, +}; +static lwm2m_object_t server_object = { + .impl = &impl, +}; + +LIST(server_list); +static lwm2m_server_t server_instances[MAX_COUNT]; +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +create_instance(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + int i; + + instance = get_by_id(instance_id, NULL); + if(instance != NULL) { + /* An instance with this id is already registered */ + if(status) { + *status = LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + return NULL; + } + + for(i = 0; i < MAX_COUNT; i++) { + if(server_instances[i].instance.instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + server_instances[i].instance.callback = lwm2m_callback; + server_instances[i].instance.object_id = LWM2M_OBJECT_SERVER_ID; + server_instances[i].instance.instance_id = instance_id; + server_instances[i].instance.resource_ids = resources; + server_instances[i].instance.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + server_instances[i].server_id = 0; + server_instances[i].lifetime = 0; + list_add(server_list, &server_instances[i].instance); + + if(status) { + *status = LWM2M_STATUS_OK; + } + + return &server_instances[i].instance; + } + } + + if(status) { + *status = LWM2M_STATUS_SERVICE_UNAVAILABLE; + } + + return NULL; +} +/*---------------------------------------------------------------------------*/ +static int +delete_instance(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + + if(status) { + *status = LWM2M_STATUS_OK; + } + + if(instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + /* Remove all instances */ + while((instance = list_pop(server_list)) != NULL) { + instance->instance_id = LWM2M_OBJECT_INSTANCE_NONE; + } + return 1; + } + + instance = get_by_id(instance_id, NULL); + if(instance != NULL) { + instance->instance_id = LWM2M_OBJECT_INSTANCE_NONE; + list_remove(server_list, instance); + return 1; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_first(lwm2m_status_t *status) +{ + if(status) { + *status = LWM2M_STATUS_OK; + } + return list_head(server_list); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_next(lwm2m_object_instance_t *instance, lwm2m_status_t *status) +{ + if(status) { + *status = LWM2M_STATUS_OK; + } + return instance == NULL ? NULL : instance->next; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_by_id(uint16_t instance_id, lwm2m_status_t *status) +{ + lwm2m_object_instance_t *instance; + if(status) { + *status = LWM2M_STATUS_OK; + } + for(instance = list_head(server_list); + instance != NULL; + instance = instance->next) { + if(instance->instance_id == instance_id) { + return instance; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx) +{ + int32_t value; + lwm2m_server_t *server; + server = (lwm2m_server_t *) object; + + if(ctx->operation == LWM2M_OP_WRITE) { + LOG_DBG("Write to: %d\n", ctx->resource_id); + switch(ctx->resource_id) { + case LWM2M_SERVER_LIFETIME_ID: + lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &value); + server->lifetime = value; + break; + } + } else if(ctx->operation == LWM2M_OP_READ) { + switch(ctx->resource_id) { + case LWM2M_SERVER_SHORT_SERVER_ID: + lwm2m_object_write_int(ctx, server->server_id); + break; + case LWM2M_SERVER_LIFETIME_ID: + lwm2m_object_write_int(ctx, server->lifetime); + break; + } + } else if(ctx->operation == LWM2M_OP_EXECUTE) { + switch(ctx->resource_id) { + case LWM2M_SERVER_REG_UPDATE_TRIGGER_ID: + lwm2m_rd_client_update_triggered(); + break; + } + } else { + return LWM2M_STATUS_NOT_IMPLEMENTED; + } + + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +lwm2m_server_t * +lwm2m_server_add(uint16_t instance_id, uint16_t server_id, uint32_t lifetime) +{ + lwm2m_server_t *server; + int i; + + for(server = list_head(server_list); + server; + server = (lwm2m_server_t *)server->instance.next) { + if(server->server_id == server_id) { + /* Found a matching server */ + if(server->instance.instance_id != instance_id) { + /* Non-matching instance id */ + LOG_DBG("non-matching instance id for server %u\n", server_id); + return NULL; + } + server->lifetime = lifetime; + return server; + } else if(server->instance.instance_id == instance_id) { + /* Right instance but wrong server id */ + LOG_DBG("non-matching server id for instance %u\n", instance_id); + return NULL; + } + } + + for(i = 0; i < MAX_COUNT; i++) { + if(server_instances[i].instance.instance_id == LWM2M_OBJECT_INSTANCE_NONE) { + server_instances[i].instance.callback = lwm2m_callback; + server_instances[i].instance.object_id = LWM2M_OBJECT_SERVER_ID; + server_instances[i].instance.instance_id = instance_id; + server_instances[i].instance.resource_ids = resources; + server_instances[i].instance.resource_count = + sizeof(resources) / sizeof(lwm2m_resource_id_t); + server_instances[i].server_id = server_id; + server_instances[i].lifetime = lifetime; + list_add(server_list, &server_instances[i].instance); + + return &server_instances[i]; + } + } + + LOG_WARN("no space for more servers\n"); + + return NULL; +} /*---------------------------------------------------------------------------*/ void lwm2m_server_init(void) { - lwm2m_instance_t template = LWM2M_INSTANCE_UNUSED(0, server_resources); int i; - /* Initialize the instances */ + LOG_INFO("init\n"); + + list_init(server_list); + for(i = 0; i < MAX_COUNT; i++) { - server_instances[i] = template; - server_instances[i].id = i; + server_instances[i].instance.instance_id = LWM2M_OBJECT_INSTANCE_NONE; } - - /** - * Register this device and its handlers - the handlers - * automatically sends in the object to handle - */ - PRINTF("*** Init lwm2m-server\n"); - lwm2m_engine_register_object(&server); + lwm2m_engine_add_generic_object(&server_object); } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/services/lwm2m/lwm2m-server.h b/os/services/lwm2m/lwm2m-server.h new file mode 100644 index 0000000000000000000000000000000000000000..733b0889dc7a60b45e20f331b0409d38084ab0e9 --- /dev/null +++ b/os/services/lwm2m/lwm2m-server.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017, SICS Swedish ICT + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \addtogroup lwm2m + * @{ + * + */ +#ifndef LWM2M_SERVER_H +#define LWM2M_SERVER_H + +#include "contiki.h" + +#define LWM2M_SERVER_SHORT_SERVER_ID 0 +#define LWM2M_SERVER_LIFETIME_ID 1 +#define LWM2M_SERVER_BINDING_ID 7 +#define LWM2M_SERVER_REG_UPDATE_TRIGGER_ID 8 + +#ifdef LWM2M_SERVER_CONF_MAX_COUNT +#define LWM2M_SERVER_MAX_COUNT LWM2M_SERVER_CONF_MAX_COUNT +#else +#define LWM2M_SERVER_MAX_COUNT 2 +#endif + +typedef struct { + lwm2m_object_instance_t instance; + uint16_t server_id; + uint32_t lifetime; +} lwm2m_server_t; + +lwm2m_server_t *lwm2m_server_add(uint16_t instance_id, + uint16_t server_id, + uint32_t lifetime); + +void lwm2m_server_init(void); + +#endif /* LWM2M_SERVER_H */ +/** @} */ diff --git a/os/services/lwm2m/oma-tlv-reader.c b/os/services/lwm2m/lwm2m-tlv-reader.c similarity index 74% rename from os/services/lwm2m/oma-tlv-reader.c rename to os/services/lwm2m/lwm2m-tlv-reader.c index 58e1dcc5491c63f1ce73bef402b23621dcf92b80..cbeed6bd223775e3700a7c60f0d765ae326b1c04 100644 --- a/os/services/lwm2m/oma-tlv-reader.c +++ b/os/services/lwm2m/lwm2m-tlv-reader.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ * */ @@ -43,30 +43,32 @@ */ #include "lwm2m-object.h" -#include "oma-tlv-reader.h" -#include "oma-tlv.h" +#include "lwm2m-tlv-reader.h" +#include "lwm2m-tlv.h" +#include <string.h> /*---------------------------------------------------------------------------*/ static size_t -read_int(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_int(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value) { - oma_tlv_t tlv; + lwm2m_tlv_t tlv; size_t size; - size = oma_tlv_read(&tlv, inbuf, len); + size = lwm2m_tlv_read(&tlv, inbuf, len); if(size > 0) { - *value = oma_tlv_get_int32(&tlv); + *value = lwm2m_tlv_get_int32(&tlv); + ctx->last_value_len = tlv.length; } return size; } /*---------------------------------------------------------------------------*/ static size_t -read_string(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_string(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t stringlen) { - oma_tlv_t tlv; + lwm2m_tlv_t tlv; size_t size; - size = oma_tlv_read(&tlv, inbuf, len); + size = lwm2m_tlv_read(&tlv, inbuf, len); if(size > 0) { if(stringlen <= tlv.length) { /* The outbuffer can not contain the full string including ending zero */ @@ -74,37 +76,40 @@ read_string(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, } memcpy(value, tlv.value, tlv.length); value[tlv.length] = '\0'; + ctx->last_value_len = tlv.length; } return size; } /*---------------------------------------------------------------------------*/ static size_t -read_float32fix(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_float32fix(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits) { - oma_tlv_t tlv; + lwm2m_tlv_t tlv; size_t size; - size = oma_tlv_read(&tlv, inbuf, len); + size = lwm2m_tlv_read(&tlv, inbuf, len); if(size > 0) { - oma_tlv_float32_to_fix(&tlv, value, bits); + lwm2m_tlv_float32_to_fix(&tlv, value, bits); + ctx->last_value_len = tlv.length; } return size; } /*---------------------------------------------------------------------------*/ static size_t -read_boolean(const lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, +read_boolean(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value) { - oma_tlv_t tlv; + lwm2m_tlv_t tlv; size_t size; - size = oma_tlv_read(&tlv, inbuf, len); + size = lwm2m_tlv_read(&tlv, inbuf, len); if(size > 0) { - *value = oma_tlv_get_int32(&tlv) != 0; + *value = lwm2m_tlv_get_int32(&tlv) != 0; + ctx->last_value_len = tlv.length; } return size; } /*---------------------------------------------------------------------------*/ -const lwm2m_reader_t oma_tlv_reader = { +const lwm2m_reader_t lwm2m_tlv_reader = { read_int, read_string, read_float32fix, diff --git a/os/services/lwm2m/oma-tlv-reader.h b/os/services/lwm2m/lwm2m-tlv-reader.h similarity index 89% rename from os/services/lwm2m/oma-tlv-reader.h rename to os/services/lwm2m/lwm2m-tlv-reader.h index 7e6540c1889103aafcfa75435e896eef01599d08..15db7024db6406087ad6dcce552d5cc63385a8c6 100644 --- a/os/services/lwm2m/oma-tlv-reader.h +++ b/os/services/lwm2m/lwm2m-tlv-reader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,7 +28,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** \addtogroup oma-lwm2m +/** \addtogroup lwm2m * @{ */ /** @@ -39,12 +39,12 @@ * Niclas Finne <nfi@sics.se> */ -#ifndef OMA_TLV_READER_H_ -#define OMA_TLV_READER_H_ +#ifndef LWM2M_TLV_READER_H_ +#define LWM2M_TLV_READER_H_ #include "lwm2m-object.h" -extern const lwm2m_reader_t oma_tlv_reader; +extern const lwm2m_reader_t lwm2m_tlv_reader; -#endif /* OMA_TLV_READER_H_ */ +#endif /* LWM2M_TLV_READER_H_ */ /** @} */ diff --git a/os/services/lwm2m/lwm2m-tlv-writer.c b/os/services/lwm2m/lwm2m-tlv-writer.c new file mode 100644 index 0000000000000000000000000000000000000000..41bdc2f6ce9517d092d548205fbf169182cbc759 --- /dev/null +++ b/os/services/lwm2m/lwm2m-tlv-writer.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2015-2018, Yanzi Networks AB. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \addtogroup lwm2m + * @{ + * + */ + +/** + * \file + * Implementation of the Contiki OMA LWM2M TLV writer + * \author + * Joakim Eriksson <joakime@sics.se> + * Niclas Finne <nfi@sics.se> + */ + +#include "lwm2m-object.h" +#include "lwm2m-tlv.h" + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-tlv" +#define LOG_LEVEL LOG_LEVEL_NONE + +/*---------------------------------------------------------------------------*/ +static size_t +init_write(lwm2m_context_t *ctx) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static size_t +end_write(lwm2m_context_t *ctx) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static size_t +write_int_tlv(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, + int32_t value) +{ + uint8_t type = ctx->writer_flags & WRITER_RESOURCE_INSTANCE ? + LWM2M_TLV_TYPE_RESOURCE_INSTANCE : LWM2M_TLV_TYPE_RESOURCE; + uint16_t id = ctx->writer_flags & WRITER_RESOURCE_INSTANCE ? + ctx->resource_instance_id : ctx->resource_id; + return lwm2m_tlv_write_int32(type, id, value, outbuf, outlen); +} +/*---------------------------------------------------------------------------*/ +static size_t +write_boolean_tlv(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, + int value) +{ + return write_int_tlv(ctx, outbuf, outlen, value != 0 ? 1 : 0); +} +/*---------------------------------------------------------------------------*/ +static size_t +write_float32fix_tlv(lwm2m_context_t *ctx, uint8_t *outbuf, + size_t outlen, int32_t value, int bits) +{ + uint8_t type = ctx->writer_flags & WRITER_RESOURCE_INSTANCE ? + LWM2M_TLV_TYPE_RESOURCE_INSTANCE : LWM2M_TLV_TYPE_RESOURCE; + uint16_t id = ctx->writer_flags & WRITER_RESOURCE_INSTANCE ? + ctx->resource_instance_id : ctx->resource_id; + return lwm2m_tlv_write_float32(type, id, value, bits, outbuf, outlen); +} +/*---------------------------------------------------------------------------*/ +static size_t +write_string_tlv(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, + const char *value, size_t stringlen) +{ + lwm2m_tlv_t tlv; + tlv.type = ctx->writer_flags & WRITER_RESOURCE_INSTANCE ? + LWM2M_TLV_TYPE_RESOURCE_INSTANCE : LWM2M_TLV_TYPE_RESOURCE; + tlv.value = (uint8_t *) value; + tlv.length = (uint32_t) stringlen; + tlv.id = ctx->resource_id; + return lwm2m_tlv_write(&tlv, outbuf, outlen); +} +/*---------------------------------------------------------------------------*/ +static size_t +write_opaque_header(lwm2m_context_t *ctx, size_t payloadsize) +{ + lwm2m_tlv_t tlv; + tlv.type = LWM2M_TLV_TYPE_RESOURCE; + tlv.value = (uint8_t *) NULL; + tlv.length = (uint32_t) payloadsize; + tlv.id = ctx->resource_id; + return lwm2m_tlv_write(&tlv, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len); +} +/*---------------------------------------------------------------------------*/ +static size_t +enter_sub(lwm2m_context_t *ctx) +{ + /* set some flags in state */ + lwm2m_tlv_t tlv; + int len = 0; + LOG_DBG("Enter sub-resource rsc=%d mark:%d\n", ctx->resource_id, ctx->outbuf->len); + ctx->writer_flags |= WRITER_RESOURCE_INSTANCE; + tlv.type = LWM2M_TLV_TYPE_MULTI_RESOURCE; + tlv.length = 8; /* create an 8-bit TLV */ + tlv.value = NULL; + tlv.id = ctx->resource_id; + len = lwm2m_tlv_write(&tlv, &ctx->outbuf->buffer[ctx->outbuf->len], + ctx->outbuf->size - ctx->outbuf->len); + /* store position for deciding where to re-write the TLV when we + know the length - NOTE: either this or memmov of buffer later... */ + ctx->out_mark_pos_ri = ctx->outbuf->len; + return len; +} +/*---------------------------------------------------------------------------*/ +static size_t +exit_sub(lwm2m_context_t *ctx) +{ + /* clear out state info */ + int pos = 2; /* this is the lenght pos */ + int len; + ctx->writer_flags &= ~WRITER_RESOURCE_INSTANCE; + + if(ctx->resource_id > 0xff) { + pos++; + } + len = ctx->outbuf->len - ctx->out_mark_pos_ri; + + LOG_DBG("Exit sub-resource rsc=%d mark:%d len=%d\n", ctx->resource_id, + ctx->out_mark_pos_ri, len); + + /* update the lenght byte... Assume TLV header is pos + 1 bytes. */ + ctx->outbuf->buffer[pos + ctx->out_mark_pos_ri] = len - (pos + 1); + return 0; +} +/*---------------------------------------------------------------------------*/ +const lwm2m_writer_t lwm2m_tlv_writer = { + init_write, + end_write, + enter_sub, + exit_sub, + write_int_tlv, + write_string_tlv, + write_float32fix_tlv, + write_boolean_tlv, + write_opaque_header +}; +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/services/lwm2m/oma-tlv-writer.h b/os/services/lwm2m/lwm2m-tlv-writer.h similarity index 89% rename from os/services/lwm2m/oma-tlv-writer.h rename to os/services/lwm2m/lwm2m-tlv-writer.h index 6ae5edd14ed2e9e968793e4a0e93b372e216d699..681ccf280b028aa5d14b85911e96d573aecd1d40 100644 --- a/os/services/lwm2m/oma-tlv-writer.h +++ b/os/services/lwm2m/lwm2m-tlv-writer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,7 +28,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** \addtogroup oma-lwm2m +/** \addtogroup lwm2m * @{ */ /** @@ -39,12 +39,12 @@ * Niclas Finne <nfi@sics.se> */ -#ifndef OMA_TLV_WRITER_H_ -#define OMA_TLV_WRITER_H_ +#ifndef LWM2M_TLV_WRITER_H_ +#define LWM2M_TLV_WRITER_H_ #include "lwm2m-object.h" -extern const lwm2m_writer_t oma_tlv_writer; +extern const lwm2m_writer_t lwm2m_tlv_writer; -#endif /* OMA_TLV_WRITER_H_ */ +#endif /* LWM2M_TLV_WRITER_H_ */ /** @} */ diff --git a/os/services/lwm2m/oma-tlv.c b/os/services/lwm2m/lwm2m-tlv.c similarity index 67% rename from os/services/lwm2m/oma-tlv.c rename to os/services/lwm2m/lwm2m-tlv.c index c07df31ccfbc9a53aacd37b8a3fd8ff4b4a807b3..2bda7f8bbb3d96da7d3d52840ddd9c1152552b29 100644 --- a/os/services/lwm2m/oma-tlv.c +++ b/os/services/lwm2m/lwm2m-tlv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ */ /** - * \addtogroup oma-lwm2m + * \addtogroup lwm2m * @{ * */ @@ -44,19 +44,16 @@ #include <string.h> #include <stdint.h> -#include "oma-tlv.h" - -#define DEBUG 0 -#if DEBUG -#include <stdio.h> -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +#include "lwm2m-tlv.h" + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-tlv" +#define LOG_LEVEL LOG_LEVEL_NONE /*---------------------------------------------------------------------------*/ static inline uint8_t -get_len_type(const oma_tlv_t *tlv) +get_len_type(const lwm2m_tlv_t *tlv) { if(tlv->length < 8) { return 0; @@ -70,7 +67,7 @@ get_len_type(const oma_tlv_t *tlv) } /*---------------------------------------------------------------------------*/ size_t -oma_tlv_read(oma_tlv_t *tlv, const uint8_t *buffer, size_t len) +lwm2m_tlv_read(lwm2m_tlv_t *tlv, const uint8_t *buffer, size_t len) { uint8_t len_type; uint8_t len_pos = 1; @@ -104,7 +101,7 @@ oma_tlv_read(oma_tlv_t *tlv, const uint8_t *buffer, size_t len) } /*---------------------------------------------------------------------------*/ size_t -oma_tlv_get_size(const oma_tlv_t *tlv) +lwm2m_tlv_get_size(const lwm2m_tlv_t *tlv) { size_t size; /* first hdr + len size */ @@ -117,8 +114,11 @@ oma_tlv_get_size(const oma_tlv_t *tlv) return size; } /*---------------------------------------------------------------------------*/ +/* If the tlv->value is NULL - only the header will be generated - useful for + * large strings or opaque streaming (block transfer) + */ size_t -oma_tlv_write(const oma_tlv_t *tlv, uint8_t *buffer, size_t len) +lwm2m_tlv_write(const lwm2m_tlv_t *tlv, uint8_t *buffer, size_t buffersize) { int pos; uint8_t len_type; @@ -127,8 +127,12 @@ oma_tlv_write(const oma_tlv_t *tlv, uint8_t *buffer, size_t len) len_type = get_len_type(tlv); pos = 1 + len_type; /* ensure that we do not write too much */ - if(len < tlv->length + pos) { - PRINTF("OMA-TLV: Could not write the TLV - buffer overflow.\n"); + if(tlv->value != NULL && buffersize < tlv->length + pos) { + LOG_WARN("Could not write the TLV - buffer overflow.\n"); + return 0; + } + + if(buffersize < pos + 2) { return 0; } @@ -156,61 +160,75 @@ oma_tlv_write(const oma_tlv_t *tlv, uint8_t *buffer, size_t len) } /* finally add the value */ - memcpy(&buffer[pos], tlv->value, tlv->length); + if(tlv->value != NULL && tlv->length > 0) { + memcpy(&buffer[pos], tlv->value, tlv->length); + } - if(DEBUG) { + if(LOG_DBG_ENABLED) { int i; - PRINTF("TLV:"); - for(i = 0; i < pos + tlv->length; i++) { - PRINTF("%02x", buffer[i]); + LOG_DBG("TLV: "); + for(i = 0; i < pos + ((tlv->value != NULL) ? tlv->length : 0); i++) { + LOG_DBG_("%02x", buffer[i]); } - PRINTF("\n"); + LOG_DBG_("\n"); } - return pos + tlv->length; + return pos + ((tlv->value != NULL) ? tlv->length : 0); } /*---------------------------------------------------------------------------*/ int32_t -oma_tlv_get_int32(const oma_tlv_t *tlv) +lwm2m_tlv_get_int32(const lwm2m_tlv_t *tlv) { int i; int32_t value = 0; - /* will probably need to handle MSB as a sign bit? */ + for(i = 0; i < tlv->length; i++) { value = (value << 8) | tlv->value[i]; } + + /* Ensure that we set all the bits above what we read in */ + if(tlv->value[0] & 0x80) { + while(i < 4) { + value = value | (0xff << (i * 8)); + i++; + } + } + return value; } /*---------------------------------------------------------------------------*/ size_t -oma_tlv_write_int32(int16_t id, int32_t value, uint8_t *buffer, size_t len) +lwm2m_tlv_write_int32(uint8_t type, int16_t id, int32_t value, uint8_t *buffer, size_t len) { - oma_tlv_t tlv; - size_t tlvlen = 0; + lwm2m_tlv_t tlv; uint8_t buf[4]; int i; - PRINTF("Exporting int32 %d %ld ", id, (long)value); + int v; + int last_bit; + LOG_DBG("Exporting int32 %d %"PRId32" ", id, value); - buf[3] = value & 0xff; - value = value >> 8; - for(i = 1; value > 0 && i < 4; i++) { + v = value < 0 ? -1 : 0; + i = 0; + do { buf[3 - i] = value & 0xff; + /* check if the last MSB indicates that we need another byte */ + last_bit = (v == 0 && (value & 0x80) > 0) || (v == -1 && (value & 0x80) == 0); value = value >> 8; - } - tlvlen = i; + i++; + } while((value != v || last_bit) && i < 4); /* export INT as TLV */ - PRINTF("len: %zu\n", tlvlen); - tlv.type = OMA_TLV_TYPE_RESOURCE; - tlv.length = tlvlen; - tlv.value = &buf[3 - (tlvlen - 1)]; + LOG_DBG("len: %d\n", i); + tlv.type = type; + tlv.length = i; + tlv.value = &buf[3 - (i - 1)]; tlv.id = id; - return oma_tlv_write(&tlv, buffer, len); + return lwm2m_tlv_write(&tlv, buffer, len); } /*---------------------------------------------------------------------------*/ /* convert fixpoint 32-bit to a IEEE Float in the byte array*/ size_t -oma_tlv_write_float32(int16_t id, int32_t value, int bits, +lwm2m_tlv_write_float32(uint8_t type, int16_t id, int32_t value, int bits, uint8_t *buffer, size_t len) { int i; @@ -218,7 +236,7 @@ oma_tlv_write_float32(int16_t id, int32_t value, int bits, int32_t val = 0; int32_t v; uint8_t b[4]; - oma_tlv_t tlv; + lwm2m_tlv_t tlv; v = value; if(v < 0) { @@ -234,33 +252,38 @@ oma_tlv_write_float32(int16_t id, int32_t value, int bits, e++; } - PRINTF("Sign: %d, Fraction: %06lx 0b", value < 0, (long)val); + LOG_DBG("Sign: %d, Fraction: %06"PRIx32" 0b", value < 0, val); for(i = 0; i < 23; i++) { - PRINTF("%d", (int)((val >> (22 - i)) & 1)); + LOG_DBG_("%"PRId32"", ((val >> (22 - i)) & 1)); } - PRINTF("\nExp:%d\n", e); + LOG_DBG_("\nExp:%d\n", e); /* convert to the thing we should have */ e = e - bits + 127; + if(value == 0) { + e = 0; + } + /* is this the right byte order? */ b[0] = (value < 0 ? 0x80 : 0) | (e >> 1); b[1] = ((e & 1) << 7) | ((val >> 16) & 0x7f); b[2] = (val >> 8) & 0xff; b[3] = val & 0xff; + LOG_DBG("B=%02x%02x%02x%02x\n", b[0], b[1], b[2], b[3]); /* construct the TLV */ - tlv.type = OMA_TLV_TYPE_RESOURCE; + tlv.type = type; tlv.length = 4; tlv.value = b; tlv.id = id; - return oma_tlv_write(&tlv, buffer, len); + return lwm2m_tlv_write(&tlv, buffer, len); } /*---------------------------------------------------------------------------*/ /* convert float to fixpoint */ size_t -oma_tlv_float32_to_fix(const oma_tlv_t *tlv, int32_t *value, int bits) +lwm2m_tlv_float32_to_fix(const lwm2m_tlv_t *tlv, int32_t *value, int bits) { /* TLV needs to be 4 bytes */ int e, i; @@ -269,19 +292,19 @@ oma_tlv_float32_to_fix(const oma_tlv_t *tlv, int32_t *value, int bits) e = ((tlv->value[0] << 1) & 0xff) | (tlv->value[1] >> 7); val = (((long)tlv->value[1] & 0x7f) << 16) | (tlv->value[2] << 8) | tlv->value[3]; - PRINTF("Sign: %d, Fraction: %06lx 0b", val < 0, (long)val); + LOG_DBG("Sign: %d, Fraction: %06"PRIx32" 0b", val < 0, val); for(i = 0; i < 23; i++) { - PRINTF("%d", (int)((val >> (22 - i)) & 1)); + LOG_DBG_("%"PRId32"", ((val >> (22 - i)) & 1)); } - PRINTF("\nExp:%d => %d\n", e, e - 127); + LOG_DBG("\nExp:%d => %d\n", e, e - 127); e = e - 127 + bits; /* e corresponds to the number of times we need to roll the number */ - PRINTF("Actual e=%d\n", e); + LOG_DBG("Actual e=%d\n", e); e = e - 23; - PRINTF("E after sub %d\n", e); + LOG_DBG("E after sub %d\n", e); val = val | 1L << 23; if(e > 0) { val = val << e; @@ -294,3 +317,20 @@ oma_tlv_float32_to_fix(const oma_tlv_t *tlv, int32_t *value, int bits) } /*---------------------------------------------------------------------------*/ /** @} */ + +#if 0 +int main(int argc, char *argv[]) +{ + lwm2m_tlv_t tlv; + uint8_t data[24]; + /* Make -1 */ + tlv.length = 2; + tlv.value = data; + data[0] = 0x00; + data[1] = 0x80, + + printf("TLV:%d\n", lwm2m_tlv_get_int32(&tlv)); + + printf("Len: %d\n", lwm2m_tlv_write_int32(0, 1, -0x88987f, data, 24)); +} +#endif diff --git a/os/services/lwm2m/oma-tlv.h b/os/services/lwm2m/lwm2m-tlv.h similarity index 65% rename from os/services/lwm2m/oma-tlv.h rename to os/services/lwm2m/lwm2m-tlv.h index 1bd5fd94ab21ff2da463427421add773e982e4d3..2766263fa4e7c153308d99c56423a63eba2ba4ff 100644 --- a/os/services/lwm2m/oma-tlv.h +++ b/os/services/lwm2m/lwm2m-tlv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Yanzi Networks AB. + * Copyright (c) 2015-2018, Yanzi Networks AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,7 +28,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** \addtogroup oma-lwm2m +/** \addtogroup lwm2m * @{ */ /** @@ -39,51 +39,52 @@ * Niclas Finne <nfi@sics.se> */ -#ifndef OAM_TLV_H_ -#define OAM_TLV_H_ +#ifndef LWM2M_TLV_H_ +#define LWM2M_TLV_H_ -#include "contiki.h" +#include <stdint.h> +#include <stddef.h> enum { - OMA_TLV_TYPE_OBJECT_INSTANCE = 0, - OMA_TLV_TYPE_RESOURCE_INSTANCE = 1, - OMA_TLV_TYPE_MULTI_RESOURCE = 2, - OMA_TLV_TYPE_RESOURCE = 3 + LWM2M_TLV_TYPE_OBJECT_INSTANCE = 0, + LWM2M_TLV_TYPE_RESOURCE_INSTANCE = 1, + LWM2M_TLV_TYPE_MULTI_RESOURCE = 2, + LWM2M_TLV_TYPE_RESOURCE = 3 }; -typedef uint8_t oma_tlv_type_t; +typedef uint8_t lwm2m_tlv_type_t; typedef enum { - OMA_TLV_LEN_TYPE_NO_LEN = 0, - OMA_TLV_LEN_TYPE_8BIT_LEN = 1, - OMA_TLV_LEN_TYPE_16BIT_LEN = 2, - OMA_TLV_LEN_TYPE_24BIT_LEN = 3 -} oma_tlv_len_type_t; + LWM2M_TLV_LEN_TYPE_NO_LEN = 0, + LWM2M_TLV_LEN_TYPE_8BIT_LEN = 1, + LWM2M_TLV_LEN_TYPE_16BIT_LEN = 2, + LWM2M_TLV_LEN_TYPE_24BIT_LEN = 3 +} lwm2m_tlv_len_type_t; typedef struct { - oma_tlv_type_t type; + lwm2m_tlv_type_t type; uint16_t id; /* can be 8-bit or 16-bit when serialized */ uint32_t length; const uint8_t *value; -} oma_tlv_t; +} lwm2m_tlv_t; -size_t oma_tlv_get_size(const oma_tlv_t *tlv); +size_t lwm2m_tlv_get_size(const lwm2m_tlv_t *tlv); /* read a TLV from the buffer */ -size_t oma_tlv_read(oma_tlv_t *tlv, const uint8_t *buffer, size_t len); +size_t lwm2m_tlv_read(lwm2m_tlv_t *tlv, const uint8_t *buffer, size_t len); /* write a TLV to the buffer */ -size_t oma_tlv_write(const oma_tlv_t *tlv, uint8_t *buffer, size_t len); +size_t lwm2m_tlv_write(const lwm2m_tlv_t *tlv, uint8_t *buffer, size_t len); -int32_t oma_tlv_get_int32(const oma_tlv_t *tlv); +int32_t lwm2m_tlv_get_int32(const lwm2m_tlv_t *tlv); /* write a int as a TLV to the buffer */ -size_t oma_tlv_write_int32(int16_t id, int32_t value, uint8_t *buffer, size_t len); +size_t lwm2m_tlv_write_int32(uint8_t type, int16_t id, int32_t value, uint8_t *buffer, size_t len); /* write a float converted from fixpoint as a TLV to the buffer */ -size_t oma_tlv_write_float32(int16_t id, int32_t value, int bits, uint8_t *buffer, size_t len); +size_t lwm2m_tlv_write_float32(uint8_t type, int16_t id, int32_t value, int bits, uint8_t *buffer, size_t len); /* convert TLV with float32 to fixpoint */ -size_t oma_tlv_float32_to_fix(const oma_tlv_t *tlv, int32_t *value, int bits); +size_t lwm2m_tlv_float32_to_fix(const lwm2m_tlv_t *tlv, int32_t *value, int bits); -#endif /* OAM_TLV_H_ */ +#endif /* LWM2M_TLV_H_ */ /** @} */ diff --git a/os/services/orchestra/orchestra-rule-unicast-per-neighbor-rpl-storing.c b/os/services/orchestra/orchestra-rule-unicast-per-neighbor-rpl-storing.c index fbafa4654ce520520d9e561a7406be78f26cc113..723b9e847f2774cc24a774448e92a109227946d9 100644 --- a/os/services/orchestra/orchestra-rule-unicast-per-neighbor-rpl-storing.c +++ b/os/services/orchestra/orchestra-rule-unicast-per-neighbor-rpl-storing.c @@ -44,10 +44,7 @@ #include "orchestra.h" #include "net/ipv6/uip-ds6-route.h" #include "net/packetbuf.h" -#include "rpl.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ +#include "net/routing/routing.h" /* * The body of this rule should be compiled only when "nbr_routes" is available, diff --git a/os/services/orchestra/orchestra.c b/os/services/orchestra/orchestra.c index 3ea78ca960855c0c32a16bd9959df77f9a49ba8d..8b9929c03eb2a9e736c3259eb3135f9ca11bdf1c 100644 --- a/os/services/orchestra/orchestra.c +++ b/os/services/orchestra/orchestra.c @@ -40,10 +40,12 @@ #include "orchestra.h" #include "net/packetbuf.h" #include "net/ipv6/uip-icmp6.h" -#include "rpl.h" -#if UIP_CONF_IPV6_RPL_LITE == 0 -#include "rpl-private.h" -#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */ +#include "net/routing/routing.h" +#if ROUTING_CONF_RPL_LITE +#include "net/routing/rpl-lite/rpl.h" +#elif ROUTING_CONF_RPL_CLASSIC +#include "net/routing/rpl-classic/rpl.h" +#endif #define DEBUG DEBUG_PRINT #include "net/ipv6/uip-debug.h" diff --git a/os/services/orchestra/orchestra.h b/os/services/orchestra/orchestra.h index b948a298551367d80515d762bc1fcaa0db84f932..32450466dbb5c3b24015b13ee60750f85eb3c4c2 100644 --- a/os/services/orchestra/orchestra.h +++ b/os/services/orchestra/orchestra.h @@ -39,8 +39,6 @@ #define __ORCHESTRA_H__ #include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-conf.h" -#include "net/mac/tsch/tsch-schedule.h" #include "orchestra-conf.h" /* The structure of an Orchestra rule */ diff --git a/os/services/rpl-border-router/Makefile.rpl-border-router b/os/services/rpl-border-router/Makefile.rpl-border-router new file mode 100644 index 0000000000000000000000000000000000000000..61ba5fa593da52e29a8771e68babd97fbc0a7b28 --- /dev/null +++ b/os/services/rpl-border-router/Makefile.rpl-border-router @@ -0,0 +1,8 @@ +include $(CONTIKI)/Makefile.identify-target + +# Include either native or embedded BR +ifeq ($(TARGET),native) + MODULES += os/services/rpl-border-router/native +else + MODULES += os/services/rpl-border-router/embedded +endif diff --git a/os/services/rpl-border-router/embedded/Makefile.embedded b/os/services/rpl-border-router/embedded/Makefile.embedded new file mode 100644 index 0000000000000000000000000000000000000000..c62f7df547a772c592335aed5691079d4ef8d144 --- /dev/null +++ b/os/services/rpl-border-router/embedded/Makefile.embedded @@ -0,0 +1,9 @@ +$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c + (cd $(CONTIKI)/tools && $(MAKE) tunslip6) + +PREFIX ?= fd00::1/64 +connect-router: $(CONTIKI)/tools/tunslip6 + sudo $(CONTIKI)/tools/tunslip6 $(PREFIX) + +connect-router-cooja: $(CONTIKI)/tools/tunslip6 + sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 $(PREFIX) diff --git a/examples/rpl-border-router/embedded/README.md b/os/services/rpl-border-router/embedded/README.md similarity index 100% rename from examples/rpl-border-router/embedded/README.md rename to os/services/rpl-border-router/embedded/README.md diff --git a/examples/rpl-border-router/embedded/border-router-embedded.c b/os/services/rpl-border-router/embedded/border-router-embedded.c similarity index 91% rename from examples/rpl-border-router/embedded/border-router-embedded.c rename to os/services/rpl-border-router/embedded/border-router-embedded.c index d1d8cdafc35dc960f601308f5d1af99baf560466..6b565a7ffc0fb9fcd4968216fa0c819f0c7ac736 100644 --- a/examples/rpl-border-router/embedded/border-router-embedded.c +++ b/os/services/rpl-border-router/embedded/border-router-embedded.c @@ -36,10 +36,14 @@ */ #include "contiki.h" -#include "rpl.h" +#include "net/routing/routing.h" +#if PLATFORM_SUPPORTS_BUTTON_HAL +#include "dev/button-hal.h" +#else #include "dev/button-sensor.h" +#endif #include "dev/slip.h" -#include "border-router-common.h" +#include "rpl-border-router.h" /*---------------------------------------------------------------------------*/ /* Log configuration */ @@ -68,7 +72,9 @@ PROCESS_THREAD(border_router_process, ev, data) PROCESS_PAUSE(); +#if !PLATFORM_SUPPORTS_BUTTON_HAL SENSORS_ACTIVATE(button_sensor); +#endif LOG_INFO("RPL-Border router started\n"); @@ -86,13 +92,13 @@ PROCESS_THREAD(border_router_process, ev, data) while(1) { PROCESS_YIELD(); - if(ev == sensors_event && data == &button_sensor) { - LOG_INFO("Initiating global repair\n"); -#if UIP_CONF_IPV6_RPL_LITE - rpl_global_repair(); +#if PLATFORM_SUPPORTS_BUTTON_HAL + if(ev == button_hal_release_event) { #else - rpl_repair_root(RPL_DEFAULT_INSTANCE); + if(ev == sensors_event && data == &button_sensor) { #endif + LOG_INFO("Initiating global repair\n"); + NETSTACK_ROUTING.global_repair("Button press"); } } diff --git a/examples/rpl-border-router/embedded/slip-bridge.c b/os/services/rpl-border-router/embedded/slip-bridge.c similarity index 87% rename from examples/rpl-border-router/embedded/slip-bridge.c rename to os/services/rpl-border-router/embedded/slip-bridge.c index cb85793f08431e694c1b1a217a86627aea917ad1..c40447d7f032bef49947967c739f9562c71ba55f 100644 --- a/examples/rpl-border-router/embedded/slip-bridge.c +++ b/os/services/rpl-border-router/embedded/slip-bridge.c @@ -62,7 +62,7 @@ request_prefix(void) uip_buf[0] = '?'; uip_buf[1] = 'P'; uip_len = 2; - slip_send(); + slip_write(uip_buf, uip_len); uip_clear_buf(); } /*---------------------------------------------------------------------------*/ @@ -70,22 +70,27 @@ static void slip_input_callback(void) { LOG_DBG("SIN: %u\n", uip_len); - if(uip_buf[0] == '!') { - LOG_INFO("Got configuration message of type %c\n", uip_buf[1]); - uip_clear_buf(); - if(uip_buf[1] == 'P') { + if(uip_buf[UIP_LLH_LEN] == '!') { + LOG_INFO("Got configuration message of type %c\n", + uip_buf[UIP_LLH_LEN + 1]); + if(uip_buf[UIP_LLH_LEN + 1] == 'P') { uip_ipaddr_t prefix; /* Here we set a prefix !!! */ memset(&prefix, 0, 16); - memcpy(&prefix, &uip_buf[2], 8); + memcpy(&prefix, &uip_buf[UIP_LLH_LEN + 2], 8); + + uip_clear_buf(); + LOG_INFO("Setting prefix "); LOG_INFO_6ADDR(&prefix); LOG_INFO_("\n"); set_prefix_64(&prefix); } - } else if(uip_buf[0] == '?') { - LOG_INFO("Got request message of type %c\n", uip_buf[1]); - if(uip_buf[1] == 'M') { + uip_clear_buf(); + + } else if(uip_buf[UIP_LLH_LEN] == '?') { + LOG_INFO("Got request message of type %c\n", uip_buf[UIP_LLH_LEN + 1]); + if(uip_buf[UIP_LLH_LEN + 1] == 'M') { char *hexchar = "0123456789abcdef"; int j; /* this is just a test so far... just to see if it works */ @@ -95,13 +100,14 @@ slip_input_callback(void) uip_buf[3 + j * 2] = hexchar[uip_lladdr.addr[j] & 15]; } uip_len = 18; - slip_send(); + slip_write(uip_buf, uip_len); } uip_clear_buf(); + } else { + /* Save the last sender received over SLIP to avoid bouncing the + packet back if no route is found */ + uip_ipaddr_copy(&last_sender, &UIP_IP_BUF->srcipaddr); } - /* Save the last sender received over SLIP to avoid bouncing the - packet back if no route is found */ - uip_ipaddr_copy(&last_sender, &UIP_IP_BUF->srcipaddr); } /*---------------------------------------------------------------------------*/ static void diff --git a/examples/platform-specific/jn516x/rpl/tools/rpl-tools.h b/os/services/rpl-border-router/module-macros.h similarity index 89% rename from examples/platform-specific/jn516x/rpl/tools/rpl-tools.h rename to os/services/rpl-border-router/module-macros.h index f14ec1d86a7729768d5b5c5fec6aecea2b8ebb0e..f3fad0b9bc6f91d7b7d361a0ab4ad3af62c0e9e1 100644 --- a/examples/platform-specific/jn516x/rpl/tools/rpl-tools.h +++ b/os/services/rpl-border-router/module-macros.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, SICS Swedish ICT. + * Copyright (c) 2017, RISE SICS * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,10 +27,6 @@ * SUCH DAMAGE. * */ -/** - * \author Simon Duquennoy <simonduq@sics.se> - */ - -void rpl_tools_init(uip_ipaddr_t *br_prefix); -void print_network_status(void); +#define BUILD_WITH_RPL_BORDER_ROUTER 1 +#define UIP_FALLBACK_INTERFACE rpl_interface diff --git a/os/services/rpl-border-router/native/Makefile.native b/os/services/rpl-border-router/native/Makefile.native new file mode 100644 index 0000000000000000000000000000000000000000..a225e1666492ec5ffb7023c9295062804f656f37 --- /dev/null +++ b/os/services/rpl-border-router/native/Makefile.native @@ -0,0 +1,13 @@ +MODULES += os/services/slip-cmd +MODULES += os/services/shell + +MAKE_MAC = MAKE_MAC_OTHER +MAKE_NET = MAKE_NET_IPV6 + + +PREFIX ?= fd00::1/64 +connect-router: border-router.native + sudo ./border-router.native $(PREFIX) + +connect-router-cooja: border-router.native + sudo ./border-router.native -a localhost $(PREFIX) diff --git a/examples/rpl-border-router/native/README.md b/os/services/rpl-border-router/native/README.md similarity index 100% rename from examples/rpl-border-router/native/README.md rename to os/services/rpl-border-router/native/README.md diff --git a/examples/rpl-border-router/native/border-router-cmds.c b/os/services/rpl-border-router/native/border-router-cmds.c similarity index 52% rename from examples/rpl-border-router/native/border-router-cmds.c rename to os/services/rpl-border-router/native/border-router-cmds.c index 75788a920a73b270e28d6031cfb806b2871a636f..9d0e2eb9f58fa755b8be22ab4bcd43e289504281 100644 --- a/examples/rpl-border-router/native/border-router-cmds.c +++ b/os/services/rpl-border-router/native/border-router-cmds.c @@ -40,9 +40,11 @@ #include "border-router.h" #include "border-router-cmds.h" #include "dev/serial-line.h" -#include "rpl.h" +#include "net/routing/routing.h" #include "net/ipv6/uiplib.h" #include <string.h> +#include "shell.h" +#include <stdio.h> #define DEBUG DEBUG_NONE #include "net/ipv6/uip-debug.h" @@ -54,6 +56,56 @@ void nbr_print_stat(void); /*---------------------------------------------------------------------------*/ PROCESS(border_router_cmd_process, "Border router cmd process"); +/*---------------------------------------------------------------------------*/ +static const uint8_t * +hextoi(const uint8_t *buf, int len, int *v) +{ + *v = 0; + for(; len > 0; len--, buf++) { + if(*buf >= '0' && *buf <= '9') { + *v = (*v << 4) + ((*buf - '0') & 0xf); + } else if(*buf >= 'a' && *buf <= 'f') { + *v = (*v << 4) + ((*buf - 'a' + 10) & 0xf); + } else if(*buf >= 'A' && *buf <= 'F') { + *v = (*v << 4) + ((*buf - 'A' + 10) & 0xf); + } else { + break; + } + } + return buf; +} +/*---------------------------------------------------------------------------*/ +static const uint8_t * +dectoi(const uint8_t *buf, int len, int *v) +{ + int negative = 0; + *v = 0; + if(len <= 0) { + return buf; + } + if(*buf == '$') { + return hextoi(buf + 1, len - 1, v); + } + if(*buf == '0' && *(buf + 1) == 'x' && len > 2) { + return hextoi(buf + 2, len - 2, v); + } + if(*buf == '-') { + negative = 1; + buf++; + } + for(; len > 0; len--, buf++) { + if(*buf < '0' || *buf > '9') { + break; + } + *v = (*v * 10) + ((*buf - '0') & 0xf); + } + if(negative) { + *v = - *v; + } + return buf; +} +/*---------------------------------------------------------------------------*/ + /*---------------------------------------------------------------------------*/ /* TODO: the below code needs some way of identifying from where the command */ /* comes. In this case it can be from stdin or from SLIP. */ @@ -64,35 +116,60 @@ border_router_cmd_handler(const uint8_t *data, int len) /* handle global repair, etc here */ if(data[0] == '!') { PRINTF("Got configuration message of type %c\n", data[1]); - if(data[1] == 'G' && command_context == CMD_CONTEXT_STDIO) { - /* This is supposed to be from stdin */ - printf("Performing Global Repair...\n"); -#if UIP_CONF_IPV6_RPL_LITE - rpl_global_repair(); -#else - rpl_repair_root(RPL_DEFAULT_INSTANCE); -#endif - return 1; - } else if(data[1] == 'M' && command_context == CMD_CONTEXT_RADIO) { - /* We need to know that this is from the slip-radio here. */ - PRINTF("Setting MAC address\n"); - border_router_set_mac(&data[2]); - return 1; - } else if(data[1] == 'C' && command_context == CMD_CONTEXT_RADIO) { - /* We need to know that this is from the slip-radio here. */ - printf("Channel is:%d\n", data[2]); - return 1; - } else if(data[1] == 'R' && command_context == CMD_CONTEXT_RADIO) { + if(command_context == CMD_CONTEXT_STDIO) { + switch(data[1]) { + case 'G': + /* This is supposed to be from stdin */ + printf("Performing Global Repair...\n"); + NETSTACK_ROUTING.global_repair("Command"); + return 1; + case 'C': { + /* send on a set-param thing! */ + uint8_t set_param[] = {'!', 'V', 0, RADIO_PARAM_CHANNEL, 0, 0 }; + int channel = -1; + dectoi(&data[2], len - 2, &channel); + if(channel >= 0) { + set_param[5] = channel & 0xff; + write_to_slip(set_param, sizeof(set_param)); + } + return 1; + } + case 'P': { + /* send on a set-param thing! */ + uint8_t set_param[] = {'!', 'V', 0, RADIO_PARAM_PAN_ID, 0, 0 }; + int pan_id; + dectoi(&data[2], len - 2, &pan_id); + set_param[4] = (pan_id >> 8) & 0xff; + set_param[5] = pan_id & 0xff; + write_to_slip(set_param, sizeof(set_param)); + return 1; + } + default: + return 0; + } + } else if(command_context == CMD_CONTEXT_RADIO) { /* We need to know that this is from the slip-radio here. */ - PRINTF("Packet data report for sid:%d st:%d tx:%d\n", - data[2], data[3], data[4]); - packet_sent(data[2], data[3], data[4]); - return 1; - } else if(data[1] == 'D' && command_context == CMD_CONTEXT_RADIO) { - /* We need to know that this is from the slip-radio here... */ - PRINTF("Sensor data received\n"); - border_router_set_sensors((const char *)&data[2], len - 2); - return 1; + switch(data[1]) { + case 'M': + PRINTF("Setting MAC address\n"); + border_router_set_mac(&data[2]); + return 1; + case 'V': + if(data[3] == RADIO_PARAM_CHANNEL) { + printf("Channel is %d\n", data[5]); + } + if(data[3] == RADIO_PARAM_PAN_ID) { + printf("PAN_ID is 0x%04x\n", (data[4] << 8) + data[5]); + } + return 1; + case 'R': + PRINTF("Packet data report for sid:%d st:%d tx:%d\n", + data[2], data[3], data[4]); + packet_sent(data[2], data[3], data[4]); + return 1; + default: + return 0; + } } } else if(data[0] == '?') { PRINTF("Got request message of type %c\n", data[1]); @@ -110,8 +187,14 @@ border_router_cmd_handler(const uint8_t *data, int len) cmd_send(buf, 18); return 1; } else if(data[1] == 'C' && command_context == CMD_CONTEXT_STDIO) { - /* send on! */ - write_to_slip(data, len); + /* send on a set-param thing! */ + uint8_t set_param[] = {'?', 'V', 0, RADIO_PARAM_CHANNEL}; + write_to_slip(set_param, sizeof(set_param)); + return 1; + } else if(data[1] == 'P' && command_context == CMD_CONTEXT_STDIO) { + /* send on a set-param thing! */ + uint8_t set_param[] = {'?', 'V', 0, RADIO_PARAM_PAN_ID}; + write_to_slip(set_param, sizeof(set_param)); return 1; } else if(data[1] == 'S') { border_router_print_stat(); @@ -132,17 +215,33 @@ border_router_cmd_output(const uint8_t *data, int data_len) printf("\n"); } /*---------------------------------------------------------------------------*/ +static void +serial_shell_output(const char *str) +{ + printf("%s", str); +} +/*---------------------------------------------------------------------------*/ + PROCESS_THREAD(border_router_cmd_process, ev, data) { + static struct pt shell_input_pt; PROCESS_BEGIN(); PRINTF("Started br-cmd process\n"); + + shell_init(); + while(1) { PROCESS_YIELD(); if(ev == serial_line_event_message && data != NULL) { - PRINTF("Got serial data!!! %s of len: %d\n", + PRINTF("Got serial data!!! %s of len: %lu\n", (char *)data, strlen((char *)data)); command_context = CMD_CONTEXT_STDIO; - cmd_input(data, strlen((char *)data)); + if(cmd_input(data, strlen((char *)data))) { + /* Commnand executed - all is fine */ + } else { + /* did not find command - run shell and see if ... */ + PROCESS_PT_SPAWN(&shell_input_pt, shell_input(&shell_input_pt, serial_shell_output, data)); + } } } PROCESS_END(); diff --git a/examples/rpl-border-router/native/border-router-cmds.h b/os/services/rpl-border-router/native/border-router-cmds.h similarity index 100% rename from examples/rpl-border-router/native/border-router-cmds.h rename to os/services/rpl-border-router/native/border-router-cmds.h diff --git a/examples/rpl-border-router/native/border-router-mac.c b/os/services/rpl-border-router/native/border-router-mac.c similarity index 94% rename from examples/rpl-border-router/native/border-router-mac.c rename to os/services/rpl-border-router/native/border-router-mac.c index 7b002183ed183c7975b1d51981a9ffec5dfa1b93..bcfb829b760bf5b8324b25d6fb1600a6f9dba977 100644 --- a/examples/rpl-border-router/native/border-router-mac.c +++ b/os/services/rpl-border-router/native/border-router-mac.c @@ -63,7 +63,7 @@ struct tx_callback { struct packetbuf_attr attrs[PACKETBUF_NUM_ATTRS]; struct packetbuf_addr addrs[PACKETBUF_NUM_ADDRS]; }; - +/*---------------------------------------------------------------------------*/ static struct tx_callback callbacks[MAX_CALLBACKS]; /*---------------------------------------------------------------------------*/ void @@ -111,6 +111,10 @@ send_packet(mac_callback_t sent, void *ptr) /* ack or not ? */ packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1); + /* Will make it send only DATA packets... for now */ + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME); + /* printf("Sending packet of type: %s \n", get_frame_type(packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE))); */ + if(NETSTACK_FRAMER.create() < 0) { /* Failed to allocate space for headers */ PRINTF("br-rdc: send failed, too large header\n"); diff --git a/examples/rpl-border-router/native/border-router-native.c b/os/services/rpl-border-router/native/border-router-native.c similarity index 82% rename from examples/rpl-border-router/native/border-router-native.c rename to os/services/rpl-border-router/native/border-router-native.c index fd5e3cde78c76555e95f4ac38909e6be0c2c6904..3da0ef000d0c55ddb7ccd3c2f8310b692a02eacb 100644 --- a/examples/rpl-border-router/native/border-router-native.c +++ b/os/services/rpl-border-router/native/border-router-native.c @@ -40,8 +40,9 @@ #include "contiki.h" #include "contiki-net.h" -#include "rpl.h" -#include "border-router-common.h" + +#include "net/routing/routing.h" +#include "rpl-border-router.h" #include "cmd.h" #include "border-router.h" #include "border-router-cmds.h" @@ -51,18 +52,11 @@ #include <stdlib.h> -#define MAX_SENSORS 4 - extern long slip_sent; extern long slip_received; static uint8_t mac_set; -static uint8_t sensor_count = 0; - -/* allocate MAX_SENSORS char[32]'s */ -static char sensors[MAX_SENSORS][32]; - extern int contiki_argc; extern char **contiki_argv; extern const char *slip_config_ipaddr; @@ -88,7 +82,7 @@ border_router_set_mac(const uint8_t *data) add them back again - a bit messy... ?*/ PROCESS_CONTEXT_BEGIN(&tcpip_process); uip_ds6_init(); - rpl_init(); + NETSTACK_ROUTING.init(); PROCESS_CONTEXT_END(&tcpip_process); mac_set = 1; @@ -101,30 +95,6 @@ border_router_print_stat() printf("bytes sent over SLIP: %ld\n", slip_sent); } /*---------------------------------------------------------------------------*/ -/* Format: <name=value>;<name=value>;...;<name=value>*/ -/* this function just cut at ; and store in the sensor array */ -void -border_router_set_sensors(const char *data, int len) -{ - int i; - int last_pos = 0; - int sc = 0; - for(i = 0; i < len; i++) { - if(data[i] == ';') { - sensors[sc][i - last_pos] = 0; - memcpy(sensors[sc++], &data[last_pos], i - last_pos); - last_pos = i + 1; /* skip the ';' */ - } - if(sc == MAX_SENSORS) { - sensor_count = sc; - return; - } - } - sensors[sc][len - last_pos] = 0; - memcpy(sensors[sc++], &data[last_pos], len - last_pos); - sensor_count = sc; -} -/*---------------------------------------------------------------------------*/ PROCESS_THREAD(border_router_process, ev, data) { static struct etimer et; diff --git a/examples/rpl-border-router/native/border-router.h b/os/services/rpl-border-router/native/border-router.h similarity index 100% rename from examples/rpl-border-router/native/border-router.h rename to os/services/rpl-border-router/native/border-router.h diff --git a/examples/rpl-border-router/native/project-conf.h b/os/services/rpl-border-router/native/module-macros.h similarity index 88% rename from examples/rpl-border-router/native/project-conf.h rename to os/services/rpl-border-router/native/module-macros.h index 841a31f6776037b39e58c8d589f564a9a05d67e1..6527738adc00aefa59ac1028ef7c3be3e5d785fc 100644 --- a/examples/rpl-border-router/native/project-conf.h +++ b/os/services/rpl-border-router/native/module-macros.h @@ -27,13 +27,6 @@ * SUCH DAMAGE. */ -#ifndef PROJECT_ROUTER_CONF_H_ -#define PROJECT_ROUTER_CONF_H_ - -#define BORDER_ROUTER_CONF_WEBSERVER 1 - -#define UIP_FALLBACK_INTERFACE rpl_interface - /* use a non-default network driver */ #define NETSTACK_CONF_NETWORK sicslowpan_driver @@ -42,14 +35,9 @@ #define SLIP_DEV_CONF_SEND_DELAY (CLOCK_SECOND / 32) -#define WEBSERVER_CONF_CFS_CONNS 2 - #define SERIALIZE_ATTRIBUTES 1 -#define UIP_CONF_TCP 1 #define CMD_CONF_OUTPUT border_router_cmd_output /* used by wpcap (see /cpu/native/net/wpcap-drv.c) */ #define SELECT_CALLBACK 1 - -#endif /* PROJECT_ROUTER_CONF_H_ */ diff --git a/examples/rpl-border-router/native/slip-config.c b/os/services/rpl-border-router/native/slip-config.c similarity index 100% rename from examples/rpl-border-router/native/slip-config.c rename to os/services/rpl-border-router/native/slip-config.c diff --git a/examples/rpl-border-router/native/slip-dev.c b/os/services/rpl-border-router/native/slip-dev.c similarity index 100% rename from examples/rpl-border-router/native/slip-dev.c rename to os/services/rpl-border-router/native/slip-dev.c diff --git a/examples/rpl-border-router/native/tun-bridge.c b/os/services/rpl-border-router/native/tun-bridge.c similarity index 100% rename from examples/rpl-border-router/native/tun-bridge.c rename to os/services/rpl-border-router/native/tun-bridge.c diff --git a/examples/rpl-border-router/common/border-router-common.c b/os/services/rpl-border-router/rpl-border-router.c similarity index 84% rename from examples/rpl-border-router/common/border-router-common.c rename to os/services/rpl-border-router/rpl-border-router.c index ba328877798b880da64ab5b3c5fdc5986a2e4703..f07a41fdd4561f337890e00417cd2e63381d2e45 100644 --- a/examples/rpl-border-router/common/border-router-common.c +++ b/os/services/rpl-border-router/rpl-border-router.c @@ -31,8 +31,8 @@ */ #include "contiki.h" -#include "border-router-common.h" -#include "rpl-dag-root.h" +#include "net/routing/routing.h" +#include "rpl-border-router.h" /* Log configuration */ #include "sys/log.h" @@ -64,6 +64,14 @@ void set_prefix_64(uip_ipaddr_t *prefix_64) { prefix_set = 1; - rpl_dag_root_init(prefix_64, NULL); - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_set_prefix(prefix_64, NULL); + NETSTACK_ROUTING.root_start(); } +/*---------------------------------------------------------------------------*/ +void +rpl_border_router_init(void) +{ + PROCESS_NAME(border_router_process); + process_start(&border_router_process, NULL); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/rpl-border-router/common/border-router-common.h b/os/services/rpl-border-router/rpl-border-router.h similarity index 98% rename from examples/rpl-border-router/common/border-router-common.h rename to os/services/rpl-border-router/rpl-border-router.h index 25d58aab09cfec3bc389bc65565cee26e403e8c0..50d66ad059424c3c5c111dcdd64311bd32c96cbd 100644 --- a/examples/rpl-border-router/common/border-router-common.h +++ b/os/services/rpl-border-router/rpl-border-router.h @@ -36,5 +36,6 @@ extern uint8_t prefix_set; +void rpl_border_router_init(void); void print_local_addresses(void); void set_prefix_64(uip_ipaddr_t *prefix_64); diff --git a/os/services/shell/shell-commands.c b/os/services/shell/shell-commands.c index 7c14e1ef54c83c2a4b30b954b73068d90736259a..3dbce09f204e86d1e2cb6d1020630ed377b91cfe 100644 --- a/os/services/shell/shell-commands.c +++ b/os/services/shell/shell-commands.c @@ -53,19 +53,17 @@ #include "net/ipv6/uip-ds6.h" #if MAC_CONF_WITH_TSCH #include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-adaptive-timesync.h" -#include "net/mac/tsch/tsch-queue.h" -#include "net/mac/tsch/tsch-log.h" -#include "net/mac/tsch/tsch-private.h" #endif /* MAC_CONF_WITH_TSCH */ -#if UIP_CONF_IPV6_RPL_LITE -#include "net/rpl-lite/rpl.h" -#elif UIP_CONF_IPV6_RPL_CLASSIC -#include "net/rpl-classic/rpl.h" -#include "net/rpl-classic/rpl-private.h" -#endif +#include "net/routing/routing.h" #include "net/mac/llsec802154.h" +/* For RPL-specific commands */ +#if ROUTING_CONF_RPL_LITE +#include "net/routing/rpl-lite/rpl.h" +#elif ROUTING_CONF_RPL_CLASSIC +#include "net/routing/rpl-classic/rpl.h" +#endif + #include <stdlib.h> #define PING_TIMEOUT (5 * CLOCK_SECOND) @@ -98,7 +96,7 @@ ds6_nbr_state_to_str(uint8_t state) return "Unknown"; } } -#if UIP_CONF_IPV6_RPL_LITE +#if ROUTING_CONF_RPL_LITE /*---------------------------------------------------------------------------*/ static const char * rpl_state_to_str(enum rpl_dag_state state) @@ -146,7 +144,55 @@ rpl_ocp_to_str(int ocp) return "Unknown"; } } -#endif /* UIP_CONF_IPV6_RPL_LITE */ +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(cmd_rpl_status(struct pt *pt, shell_output_func output, char *args)) +{ + PT_BEGIN(pt); + + SHELL_OUTPUT(output, "RPL status:\n"); + if(!curr_instance.used) { + SHELL_OUTPUT(output, "-- Instance: None\n"); + } else { + SHELL_OUTPUT(output, "-- Instance: %u\n", curr_instance.instance_id); + if(NETSTACK_ROUTING.node_is_root()) { + SHELL_OUTPUT(output, "-- DAG root\n"); + } else { + SHELL_OUTPUT(output, "-- DAG node\n"); + } + SHELL_OUTPUT(output, "-- DAG: "); + shell_output_6addr(output, &curr_instance.dag.dag_id); + SHELL_OUTPUT(output, ", version %u\n", curr_instance.dag.version); + SHELL_OUTPUT(output, "-- Prefix: "); + shell_output_6addr(output, &curr_instance.dag.prefix_info.prefix); + SHELL_OUTPUT(output, "/%u\n", curr_instance.dag.prefix_info.length); + SHELL_OUTPUT(output, "-- MOP: %s\n", rpl_mop_to_str(curr_instance.mop)); + SHELL_OUTPUT(output, "-- OF: %s\n", rpl_ocp_to_str(curr_instance.of->ocp)); + SHELL_OUTPUT(output, "-- Hop rank increment: %u\n", curr_instance.min_hoprankinc); + SHELL_OUTPUT(output, "-- Default lifetime: %lu seconds\n", RPL_LIFETIME(curr_instance.default_lifetime)); + + SHELL_OUTPUT(output, "-- State: %s\n", rpl_state_to_str(curr_instance.dag.state)); + SHELL_OUTPUT(output, "-- Preferred parent: "); + if(curr_instance.dag.preferred_parent) { + shell_output_6addr(output, rpl_neighbor_get_ipaddr(curr_instance.dag.preferred_parent)); + SHELL_OUTPUT(output, " (last DTSN: %u)\n", curr_instance.dag.preferred_parent->dtsn); + } else { + SHELL_OUTPUT(output, "None\n"); + } + SHELL_OUTPUT(output, "-- Rank: %u\n", curr_instance.dag.rank); + SHELL_OUTPUT(output, "-- Lowest rank: %u (%u)\n", curr_instance.dag.lowest_rank, curr_instance.max_rankinc); + SHELL_OUTPUT(output, "-- DTSN out: %u\n", curr_instance.dtsn_out); + SHELL_OUTPUT(output, "-- DAO sequence: last sent %u, last acked %u\n", + curr_instance.dag.dao_last_seqno, curr_instance.dag.dao_last_acked_seqno); + SHELL_OUTPUT(output, "-- Trickle timer: current %u, min %u, max %u, redundancy %u\n", + curr_instance.dag.dio_intcurrent, curr_instance.dio_intmin, + curr_instance.dio_intmin + curr_instance.dio_intdoubl, curr_instance.dio_redundancy); + + } + + PT_END(pt); +} +#endif /* ROUTING_CONF_RPL_LITE */ /*---------------------------------------------------------------------------*/ static void echo_reply_handler(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data, uint16_t datalen) @@ -172,8 +218,11 @@ PT_THREAD(cmd_ping(struct pt *pt, shell_output_func output, char *args)) /* Get argument (remote IPv6) */ SHELL_ARGS_NEXT(args, next_args); - if(uiplib_ipaddrconv(args, &remote_addr) == 0) { - SHELL_OUTPUT(output, "Invalid IPv6: %s\n", args); + if(args == NULL) { + SHELL_OUTPUT(output, "Destination IPv6 address is not specified\n"); + PT_EXIT(pt); + } else if(uiplib_ipaddrconv(args, &remote_addr) == 0) { + SHELL_OUTPUT(output, "Invalid IPv6 address: %s\n", args); PT_EXIT(pt); } @@ -288,7 +337,7 @@ PT_THREAD(cmd_help(struct pt *pt, shell_output_func output, char *args)) PT_END(pt); } -#if UIP_CONF_IPV6_RPL_LITE +#if UIP_CONF_IPV6_RPL /*---------------------------------------------------------------------------*/ static PT_THREAD(cmd_rpl_set_root(struct pt *pt, shell_output_func output, char *args)) @@ -325,19 +374,19 @@ PT_THREAD(cmd_rpl_set_root(struct pt *pt, shell_output_func output, char *args)) } if(is_on) { - if(!rpl_dag_root_is_root()) { + if(!NETSTACK_ROUTING.node_is_root()) { SHELL_OUTPUT(output, "Setting as DAG root with prefix "); shell_output_6addr(output, &prefix); SHELL_OUTPUT(output, "/64\n"); - rpl_dag_root_init(&prefix, NULL); - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_set_prefix(&prefix, NULL); + NETSTACK_ROUTING.root_start(); } else { SHELL_OUTPUT(output, "Node is already a DAG root\n"); } } else { - if(rpl_dag_root_is_root()) { + if(NETSTACK_ROUTING.node_is_root()) { SHELL_OUTPUT(output, "Setting as non-root node: leaving DAG\n"); - rpl_dag_poison_and_leave(); + NETSTACK_ROUTING.leave_network(); } else { SHELL_OUTPUT(output, "Node is not a DAG root\n"); } @@ -347,71 +396,40 @@ PT_THREAD(cmd_rpl_set_root(struct pt *pt, shell_output_func output, char *args)) } /*---------------------------------------------------------------------------*/ static -PT_THREAD(cmd_rpl_status(struct pt *pt, shell_output_func output, char *args)) +PT_THREAD(cmd_rpl_global_repair(struct pt *pt, shell_output_func output, char *args)) { PT_BEGIN(pt); - SHELL_OUTPUT(output, "RPL status:\n"); - if(!curr_instance.used) { - SHELL_OUTPUT(output, "-- Instance: None\n"); - } else { - SHELL_OUTPUT(output, "-- Instance: %u\n", curr_instance.instance_id); - if(rpl_dag_root_is_root()) { - SHELL_OUTPUT(output, "-- DAG root\n"); - } else { - SHELL_OUTPUT(output, "-- DAG node\n"); - } - SHELL_OUTPUT(output, "-- DAG: "); - shell_output_6addr(output, &curr_instance.dag.dag_id); - SHELL_OUTPUT(output, ", version %u\n", curr_instance.dag.version); - SHELL_OUTPUT(output, "-- Prefix: "); - shell_output_6addr(output, &curr_instance.dag.prefix_info.prefix); - SHELL_OUTPUT(output, "/%u\n", curr_instance.dag.prefix_info.length); - SHELL_OUTPUT(output, "-- MOP: %s\n", rpl_mop_to_str(curr_instance.mop)); - SHELL_OUTPUT(output, "-- OF: %s\n", rpl_ocp_to_str(curr_instance.of->ocp)); - SHELL_OUTPUT(output, "-- Hop rank increment: %u\n", curr_instance.min_hoprankinc); - SHELL_OUTPUT(output, "-- Default lifetime: %lu seconds\n", RPL_LIFETIME(curr_instance.default_lifetime)); - - SHELL_OUTPUT(output, "-- State: %s\n", rpl_state_to_str(curr_instance.dag.state)); - SHELL_OUTPUT(output, "-- Preferred parent: "); - shell_output_6addr(output, rpl_neighbor_get_ipaddr(curr_instance.dag.preferred_parent)); - SHELL_OUTPUT(output, "\n"); - SHELL_OUTPUT(output, "-- Rank: %u\n", curr_instance.dag.rank); - SHELL_OUTPUT(output, "-- Lowest rank: %u (%u)\n", curr_instance.dag.lowest_rank, curr_instance.max_rankinc); - SHELL_OUTPUT(output, "-- DTSN out: %u\n", curr_instance.dtsn_out); - SHELL_OUTPUT(output, "-- DAO sequence: last sent %u, last acked %u\n", - curr_instance.dag.dao_last_seqno, curr_instance.dag.dao_last_acked_seqno); - SHELL_OUTPUT(output, "-- Trickle timer: current %u, min %u, max %u, redundancy %u\n", - curr_instance.dag.dio_intcurrent, curr_instance.dio_intmin, - curr_instance.dio_intmin + curr_instance.dio_intdoubl, curr_instance.dio_redundancy); - - } + SHELL_OUTPUT(output, "Triggering routing global repair\n") + NETSTACK_ROUTING.global_repair("Shell"); PT_END(pt); } /*---------------------------------------------------------------------------*/ static -PT_THREAD(cmd_rpl_global_repair(struct pt *pt, shell_output_func output, char *args)) +PT_THREAD(cmd_rpl_local_repair(struct pt *pt, shell_output_func output, char *args)) { PT_BEGIN(pt); - SHELL_OUTPUT(output, "Triggering RPL global repair\n") - rpl_global_repair(); + SHELL_OUTPUT(output, "Triggering routing local repair\n"); + NETSTACK_ROUTING.local_repair("Shell"); PT_END(pt); } /*---------------------------------------------------------------------------*/ +#if ROUTING_CONF_RPL_LITE static -PT_THREAD(cmd_rpl_local_repair(struct pt *pt, shell_output_func output, char *args)) +PT_THREAD(cmd_rpl_refresh_routes(struct pt *pt, shell_output_func output, char *args)) { PT_BEGIN(pt); - SHELL_OUTPUT(output, "Triggering RPL local repair\n"); - rpl_local_repair("Shell"); + SHELL_OUTPUT(output, "Triggering routes refresh\n") + rpl_refresh_routes("Shell"); PT_END(pt); } -#endif /* UIP_CONF_IPV6_RPL_LITE */ +#endif /* ROUTING_CONF_RPL_LITE */ +#endif /* UIP_CONF_IPV6_RPL */ /*---------------------------------------------------------------------------*/ static PT_THREAD(cmd_ipaddr(struct pt *pt, shell_output_func output, char *args)) @@ -551,12 +569,6 @@ static PT_THREAD(cmd_routes(struct pt *pt, shell_output_func output, char *args)) { uip_ds6_defrt_t *default_route; -#if RPL_WITH_NON_STORING - rpl_ns_node_t *link; -#endif /* RPL_WITH_NON_STORING */ -#if RPL_WITH_STORING - uip_ds6_route_t *route; -#endif /* RPL_WITH_STORING */ PT_BEGIN(pt); @@ -575,16 +587,17 @@ PT_THREAD(cmd_routes(struct pt *pt, shell_output_func output, char *args)) SHELL_OUTPUT(output, "-- None\n"); } -#if RPL_WITH_NON_STORING - if(rpl_ns_num_nodes() > 0) { +#if UIP_CONF_IPV6_RPL + if(uip_sr_num_nodes() > 0) { + uip_sr_node_t *link; /* Our routing links */ - SHELL_OUTPUT(output, "Routing links (%u in total):\n", rpl_ns_num_nodes()); - link = rpl_ns_node_head(); + SHELL_OUTPUT(output, "Routing links (%u in total):\n", uip_sr_num_nodes()); + link = uip_sr_node_head(); while(link != NULL) { uip_ipaddr_t child_ipaddr; uip_ipaddr_t parent_ipaddr; - rpl_ns_get_node_global_addr(&child_ipaddr, link); - rpl_ns_get_node_global_addr(&parent_ipaddr, link->parent); + NETSTACK_ROUTING.get_sr_node_ipaddr(&child_ipaddr, link); + NETSTACK_ROUTING.get_sr_node_ipaddr(&parent_ipaddr, link->parent); SHELL_OUTPUT(output, "-- "); shell_output_6addr(output, &child_ipaddr); if(link->parent == NULL) { @@ -594,20 +607,21 @@ PT_THREAD(cmd_routes(struct pt *pt, shell_output_func output, char *args)) SHELL_OUTPUT(output, " to "); shell_output_6addr(output, &parent_ipaddr); } - if(link->lifetime != RPL_ROUTE_INFINITE_LIFETIME) { + if(link->lifetime != UIP_SR_INFINITE_LIFETIME) { SHELL_OUTPUT(output, " (lifetime: %lu seconds)\n", (unsigned long)link->lifetime); } else { SHELL_OUTPUT(output, " (lifetime: infinite)\n"); } - link = rpl_ns_node_next(link); + link = uip_sr_node_next(link); } } else { SHELL_OUTPUT(output, "No routing links\n"); } -#endif /* RPL_WITH_NON_STORING */ +#endif /* UIP_CONF_IPV6_RPL */ -#if RPL_WITH_STORING +#if (UIP_MAX_ROUTES != 0) if(uip_ds6_route_num_routes() > 0) { + uip_ds6_route_t *route; /* Our routing entries */ SHELL_OUTPUT(output, "Routing entries (%u in total):\n", uip_ds6_route_num_routes()); route = uip_ds6_route_head(); @@ -616,7 +630,7 @@ PT_THREAD(cmd_routes(struct pt *pt, shell_output_func output, char *args)) shell_output_6addr(output, &route->ipaddr); SHELL_OUTPUT(output, " via "); shell_output_6addr(output, uip_ds6_route_nexthop(route)); - if((unsigned long)route->state.lifetime != RPL_ROUTE_INFINITE_LIFETIME) { + if((unsigned long)route->state.lifetime != 0xFFFFFFFF) { SHELL_OUTPUT(output, " (lifetime: %lu seconds)\n", (unsigned long)route->state.lifetime); } else { SHELL_OUTPUT(output, " (lifetime: infinite)\n"); @@ -626,7 +640,7 @@ PT_THREAD(cmd_routes(struct pt *pt, shell_output_func output, char *args)) } else { SHELL_OUTPUT(output, "No routing entries\n"); } -#endif /* RPL_WITH_STORING */ +#endif /* (UIP_MAX_ROUTES != 0) */ PT_END(pt); } @@ -712,11 +726,6 @@ shell_commands_init(void) /* Set up Ping Reply callback */ uip_icmp6_echo_reply_callback_add(&echo_reply_notification, echo_reply_handler); - /* Start with soft log level 0 so as to minimize interference with shell */ - log_set_level("all", LOG_LEVEL_NONE); -#if MAC_CONF_WITH_TSCH && TSCH_LOG_PER_SLOT - tsch_log_stop(); -#endif /* MAC_CONF_WITH_TSCH && TSCH_LOG_PER_SLOT */ } /*---------------------------------------------------------------------------*/ struct shell_command_t shell_commands[] = { @@ -726,12 +735,17 @@ struct shell_command_t shell_commands[] = { { "ip-nbr", cmd_ip_neighbors, "'> ip-nbr': Shows all IPv6 neighbors" }, { "log", cmd_log, "'> log module level': Sets log level (0--4) for a given module (or \"all\"). For module \"mac\", level 4 also enables per-slot logging." }, { "ping", cmd_ping, "'> ping addr': Pings the IPv6 address 'addr'" }, -#if UIP_CONF_IPV6_RPL_LITE +#if UIP_CONF_IPV6_RPL { "rpl-set-root", cmd_rpl_set_root, "'> rpl-set-root 0/1 [prefix]': Sets node as root (1) or not (0). A /64 prefix can be optionally specified." }, - { "rpl-status", cmd_rpl_status, "'> rpl-status': Shows a summary of the current RPL state" }, { "rpl-local-repair", cmd_rpl_local_repair, "'> rpl-local-repair': Triggers a RPL local repair" }, +#if ROUTING_CONF_RPL_LITE + { "rpl-refresh-routes", cmd_rpl_refresh_routes, "'> rpl-refresh-routes': Refreshes all routes through a DTSN increment" }, +#endif /* ROUTING_CONF_RPL_LITE */ { "rpl-global-repair", cmd_rpl_global_repair, "'> rpl-global-repair': Triggers a RPL global repair" }, -#endif /* UIP_CONF_IPV6_RPL_LITE */ +#endif /* UIP_CONF_IPV6_RPL */ +#if ROUTING_CONF_RPL_LITE + { "rpl-status", cmd_rpl_status, "'> rpl-status': Shows a summary of the current RPL state" }, +#endif /* ROUTING_CONF_RPL_LITE */ { "routes", cmd_routes, "'> routes': Shows the route entries" }, #if MAC_CONF_WITH_TSCH { "tsch-set-coordinator", cmd_tsch_set_coordinator, "'> tsch-set-coordinator 0/1 [0/1]': Sets node as coordinator (1) or not (0). Second, optional parameter: enable (1) or disable (0) security." }, diff --git a/os/services/shell/shell.h b/os/services/shell/shell.h index d89672a13f656c81f27aec944ea9a0011c3d795c..4f1b4186c45203c700b305361f3f83573a6313f4 100644 --- a/os/services/shell/shell.h +++ b/os/services/shell/shell.h @@ -51,28 +51,28 @@ /* Helper macros to parse arguments */ #define SHELL_ARGS_INIT(args, next_args) (next_args) = (args); -#define SHELL_ARGS_NEXT(args, next_args) do { \ - (args) = (next_args); \ - if((args) != NULL) { \ - if(*(args) == '\0') { \ - (args) = NULL; \ - } else { \ - (next_args) = strchr((args), ' '); \ - if((next_args) != NULL) { \ - *(next_args) = '\0'; \ - (next_args)++; \ - } \ - } \ - } else { \ - (next_args) = NULL; \ - } \ - } while(0) +#define SHELL_ARGS_NEXT(args, next_args) do { \ + (args) = (next_args); \ + if((args) != NULL) { \ + if(*(args) == '\0') { \ + (args) = NULL; \ + } else { \ + (next_args) = strchr((args), ' '); \ + if((next_args) != NULL) { \ + *(next_args) = '\0'; \ + (next_args)++; \ + } \ + } \ + } else { \ + (next_args) = NULL; \ + } \ + } while(0) /* Printf-formatted output via a given output function */ -#define SHELL_OUTPUT(output_func, format, ...) do { \ - char buffer[128]; \ - snprintf(buffer, sizeof(buffer), format, ##__VA_ARGS__); \ - (output_func)(buffer); \ +#define SHELL_OUTPUT(output_func, format, ...) do { \ + char buffer[192]; \ + snprintf(buffer, sizeof(buffer), format, ##__VA_ARGS__); \ + (output_func)(buffer); \ } while(0); typedef void (shell_output_func)(const char *str); @@ -85,7 +85,7 @@ void shell_init(void); /** * \brief A protothread that is spawned by a Shell driver when receiving a new line. */ - PT_THREAD(shell_input(struct pt *pt, shell_output_func output, const char *cmd)); +PT_THREAD(shell_input(struct pt *pt, shell_output_func output, const char *cmd)); /** * Prints an IPv6 address diff --git a/os/services/slip-cmd/cmd.c b/os/services/slip-cmd/cmd.c index a2853efd2655dcd65f2c765dc19e697d7723b17c..c821fe77c9e6648e1a4deee29afac27ddbadcb9d 100644 --- a/os/services/slip-cmd/cmd.c +++ b/os/services/slip-cmd/cmd.c @@ -48,19 +48,18 @@ void CMD_OUTPUT(const uint8_t *data, int data_len); extern const cmd_handler_t cmd_handlers[]; /*---------------------------------------------------------------------------*/ -void +int cmd_input(const uint8_t *data, int data_len) { int i; for(i = 0; cmd_handlers[i] != NULL; i++) { if(cmd_handlers[i](data, data_len)) { /* Command has been handled */ - return; + return 1; } } - /* Unknown command */ - cmd_send((uint8_t *)"EUnknown command", 16); + return 0; } /*---------------------------------------------------------------------------*/ void diff --git a/os/services/slip-cmd/cmd.h b/os/services/slip-cmd/cmd.h index d363ac933a3c916c437fd2903b4c6b1dff5cc324..c3282b5369bef4cfaeddbe09613753dcb3bd50b0 100644 --- a/os/services/slip-cmd/cmd.h +++ b/os/services/slip-cmd/cmd.h @@ -47,7 +47,7 @@ typedef int (* cmd_handler_t)(const uint8_t *data, int len); #define CMD_HANDLERS(...) \ const cmd_handler_t cmd_handlers[] = {__VA_ARGS__, NULL} -void cmd_input(const uint8_t *data, int data_len); +int cmd_input(const uint8_t *data, int data_len); void cmd_send(const uint8_t *data, int data_len); #endif /* CMD_H_ */ diff --git a/os/services/unit-test/example-test.c b/os/services/unit-test/example-test.c index b40dc525fef2f9ee03492b25c31f2f4f0ef35444..04192642f79c25822551da2adaecf9ea0a534868 100644 --- a/os/services/unit-test/example-test.c +++ b/os/services/unit-test/example-test.c @@ -37,12 +37,12 @@ #include "contiki.h" #include "unit-test.h" -/* Register two unit tests that will be executed by using +/* Register two unit tests that will be executed by using the UNIT_TEST_RUN macro. */ UNIT_TEST_REGISTER(arithmetic, "Arith ops"); UNIT_TEST_REGISTER(string, "String ops"); -/* arithmetic: Demonstrates a test that succeeds. The exit point will be +/* arithmetic: Demonstrates a test that succeeds. The exit point will be the line where UNIT_TEST_END is called. */ UNIT_TEST(arithmetic) { @@ -58,7 +58,7 @@ UNIT_TEST(arithmetic) UNIT_TEST_END(); } -/* string: Demonstrates a test that fails. The exit point will be +/* string: Demonstrates a test that fails. The exit point will be the line where the call to UNIT_TEST_ASSERT fails. */ UNIT_TEST(string) { @@ -72,7 +72,6 @@ UNIT_TEST(string) } PROCESS(test_process, "Unit testing"); -AUTOSTART_PROCESSES(&test_process); PROCESS_THREAD(test_process, ev, data) { diff --git a/os/storage/antelope/aql-lexer.c b/os/storage/antelope/aql-lexer.c index cad604efb8a8d2ac4c1c49ba752c44ba67b8e3a6..4bdefecf2f4914ec8eb8deec5503b23c67ef1cc6 100644 --- a/os/storage/antelope/aql-lexer.c +++ b/os/storage/antelope/aql-lexer.c @@ -42,6 +42,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <strings.h> struct keyword { char *string; diff --git a/os/storage/antelope/db-options.h b/os/storage/antelope/db-options.h index f82c72edccdff4f984ddae996de71e985d680f8a..2be415f4efc3711b457a76655828918bc8fb1d3a 100644 --- a/os/storage/antelope/db-options.h +++ b/os/storage/antelope/db-options.h @@ -38,6 +38,7 @@ #define DB_OPTIONS_H #include "contiki.h" +#include "cfs-coffee-arch.h" /*----------------------------------------------------------------------------*/ @@ -143,9 +144,17 @@ /* The default relation file size to reserve when using Coffee. */ #ifndef DB_COFFEE_RESERVE_SIZE -#define DB_COFFEE_RESERVE_SIZE (128 * 1024UL) +#define DB_COFFEE_RESERVE_SIZE (COFFEE_SIZE / 8) #endif /* DB_COFFEE_RESERVE_SIZE */ +/* + * Ensure that the default size of Coffee file reservations is suitable + * for the file system size. + */ +#if DB_COFFEE_RESERVE_SIZE > (COFFEE_SIZE / 2) +#error DB_COFFEE_RESERVE_SIZE is too large for the file system. +#endif + /* The maximum size of the physical storage of a tuple (labelled a "row" in Antelope's terminology. */ #ifndef DB_MAX_CHAR_SIZE_PER_ROW diff --git a/os/storage/antelope/index.c b/os/storage/antelope/index.c index 5c96bf459e2d5dc74b92895a5d725a1a87697fc2..7e05d073859d8714bc377ee0c76ce1fdda3141e1 100644 --- a/os/storage/antelope/index.c +++ b/os/storage/antelope/index.c @@ -29,7 +29,7 @@ /** * \file - * This component forwards index calls using the generic index + * This component forwards index calls using the generic index * API to specific implementations. * \author * Nicolas Tsiftes <nvt@sics.se> @@ -241,7 +241,7 @@ index_delete(index_t *index, attribute_value_t *value) } db_result_t -index_get_iterator(index_iterator_t *iterator, index_t *index, +index_get_iterator(index_iterator_t *iterator, index_t *index, attribute_value_t *min_value, attribute_value_t *max_value) { @@ -266,15 +266,15 @@ index_get_iterator(index_iterator_t *iterator, index_t *index, range = (unsigned long)max - min; if(range > 0) { /* - * Index structures that do not have a natural ability to handle + * Index structures that do not have a natural ability to handle * range queries (e.g., a hash index) can nevertheless emulate them. * - * The range query emulation attempts to look up the key for each - * value in the search range. If the search range is sparse, this + * The range query emulation attempts to look up the key for each + * value in the search range. If the search range is sparse, this * iteration will incur a considerable overhead per found key. * - * Hence, the emulation is preferable when an external module wants - * to iterate over a narrow range of keys, for which the total + * Hence, the emulation is preferable when an external module wants + * to iterate over a narrow range of keys, for which the total * search cost is smaller than that of an iteration over all tuples * in the relation. */ @@ -294,7 +294,7 @@ index_get_iterator(index_iterator_t *iterator, index_t *index, iterator->max_value = *max_value; iterator->next_item_no = 0; - PRINTF("DB: Acquired an index iterator for %s.%s over the range (%ld,%ld)\n", + PRINTF("DB: Acquired an index iterator for %s.%s over the range (%ld,%ld)\n", index->rel->name, index->attr->name, min_value->u.long_value, max_value->u.long_value); @@ -380,7 +380,7 @@ PROCESS_THREAD(db_indexer, ev, data) PRINTF("DB: Loading the index for %s.%s...\n", index->rel->name, index->attr->name); - /* Project the values of the indexed attribute from all tuples in + /* Project the values of the indexed attribute from all tuples in the relation, and insert them into the index again. */ if(DB_ERROR(db_query(&handle, "SELECT %s FROM %s;", index->attr->name, index->rel->name))) { index->flags |= INDEX_LOAD_ERROR; diff --git a/os/storage/antelope/index.h b/os/storage/antelope/index.h index de7b28b36c5a5249f37810683980379de36eaffa..6c9863e8f80ff4787565a8c4fb6acd8da784c398 100644 --- a/os/storage/antelope/index.h +++ b/os/storage/antelope/index.h @@ -105,7 +105,7 @@ db_result_t index_load(relation_t *, attribute_t *); db_result_t index_release(index_t *); db_result_t index_insert(index_t *, attribute_value_t *, tuple_id_t); db_result_t index_delete(index_t *, attribute_value_t *); -db_result_t index_get_iterator(index_iterator_t *, index_t *, +db_result_t index_get_iterator(index_iterator_t *, index_t *, attribute_value_t *, attribute_value_t *); tuple_id_t index_get_next(index_iterator_t *); int index_exists(attribute_t *); diff --git a/os/storage/cfs/cfs-coffee.c b/os/storage/cfs/cfs-coffee.c index 75cbf730ec12ff243d3bffd7e6f6301a255c61d6..53c7eca53c9f8017e15c0121f377de714b929a74 100644 --- a/os/storage/cfs/cfs-coffee.c +++ b/os/storage/cfs/cfs-coffee.c @@ -1094,7 +1094,7 @@ cfs_read(int fd, void *buf, unsigned size) fdp = &coffee_fd_set[fd]; file = fdp->file; - + if(fdp->io_flags & CFS_COFFEE_IO_ENSURE_READ_LENGTH) { while(fdp->offset + size > file->end) { ((char *)buf)[--size] = '\0'; diff --git a/os/storage/cfs/cfs.h b/os/storage/cfs/cfs.h index 3e2452c619c4f56854668dea80c78d42ecd0da8c..4851f562a48cc3fb26b57c45360f9a72d755e82e 100644 --- a/os/storage/cfs/cfs.h +++ b/os/storage/cfs/cfs.h @@ -166,7 +166,7 @@ struct cfs_dirent { * \sa cfs_close() */ #ifndef cfs_open -CCIF int cfs_open(const char *name, int flags); +int cfs_open(const char *name, int flags); #endif /** @@ -177,7 +177,7 @@ CCIF int cfs_open(const char *name, int flags); * opened with cfs_open(). */ #ifndef cfs_close -CCIF void cfs_close(int fd); +void cfs_close(int fd); #endif /** @@ -192,7 +192,7 @@ CCIF void cfs_close(int fd); * cfs_open() and the CFS_READ flag. */ #ifndef cfs_read -CCIF int cfs_read(int fd, void *buf, unsigned int len); +int cfs_read(int fd, void *buf, unsigned int len); #endif /** @@ -207,7 +207,7 @@ CCIF int cfs_read(int fd, void *buf, unsigned int len); * cfs_open() and the CFS_WRITE flag. */ #ifndef cfs_write -CCIF int cfs_write(int fd, const void *buf, unsigned int len); +int cfs_write(int fd, const void *buf, unsigned int len); #endif /** @@ -228,7 +228,7 @@ CCIF int cfs_write(int fd, const void *buf, unsigned int len); * \sa CFS_SEEK_SET */ #ifndef cfs_seek -CCIF cfs_offset_t cfs_seek(int fd, cfs_offset_t offset, int whence); +cfs_offset_t cfs_seek(int fd, cfs_offset_t offset, int whence); #endif /** @@ -238,7 +238,7 @@ CCIF cfs_offset_t cfs_seek(int fd, cfs_offset_t offset, int whence); * \return -1 If the file could not be removed or if it doesn't exist. */ #ifndef cfs_remove -CCIF int cfs_remove(const char *name); +int cfs_remove(const char *name); #endif /** @@ -251,7 +251,7 @@ CCIF int cfs_remove(const char *name); * \sa cfs_closedir() */ #ifndef cfs_opendir -CCIF int cfs_opendir(struct cfs_dir *dirp, const char *name); +int cfs_opendir(struct cfs_dir *dirp, const char *name); #endif /** @@ -265,7 +265,7 @@ CCIF int cfs_opendir(struct cfs_dir *dirp, const char *name); * \sa cfs_closedir() */ #ifndef cfs_readdir -CCIF int cfs_readdir(struct cfs_dir *dirp, struct cfs_dirent *dirent); +int cfs_readdir(struct cfs_dir *dirp, struct cfs_dirent *dirent); #endif /** @@ -276,7 +276,7 @@ CCIF int cfs_readdir(struct cfs_dir *dirp, struct cfs_dirent *dirent); * \sa cfs_readdir() */ #ifndef cfs_closedir -CCIF void cfs_closedir(struct cfs_dir *dirp); +void cfs_closedir(struct cfs_dir *dirp); #endif #endif /* CFS_H_ */ diff --git a/os/sys/autostart.h b/os/sys/autostart.h index a2cd10eb7f7b0bffa6af4ce458df72f684359dc2..dcf91c4ef899ecd19369e2ed6fb6fe41c55dd997 100644 --- a/os/sys/autostart.h +++ b/os/sys/autostart.h @@ -44,18 +44,13 @@ #include "sys/process.h" #if ! CC_NO_VA_ARGS -#if AUTOSTART_ENABLE #define AUTOSTART_PROCESSES(...) \ struct process * const autostart_processes[] = {__VA_ARGS__, NULL} -#else /* AUTOSTART_ENABLE */ -#define AUTOSTART_PROCESSES(...) \ -extern int _dummy -#endif /* AUTOSTART_ENABLE */ #else #error "C compiler must support __VA_ARGS__ macro" #endif -CLIF extern struct process * const autostart_processes[]; +extern struct process * const autostart_processes[]; void autostart_start(struct process * const processes[]); void autostart_exit(struct process * const processes[]); diff --git a/os/sys/clock.h b/os/sys/clock.h index 3aa25b22cec385eda77a5ad742196ea2bd43680c..161527d476d10ac85d7dfe6110d94bfccc05073f 100644 --- a/os/sys/clock.h +++ b/os/sys/clock.h @@ -98,7 +98,7 @@ void clock_init(void); * * \return The current clock time, measured in system ticks. */ -CCIF clock_time_t clock_time(void); +clock_time_t clock_time(void); /** * Get the current value of the platform seconds. @@ -108,7 +108,7 @@ CCIF clock_time_t clock_time(void); * * \return The value. */ -CCIF unsigned long clock_seconds(void); +unsigned long clock_seconds(void); /** * Set the value of the platform seconds. diff --git a/os/sys/critical.h b/os/sys/critical.h new file mode 100644 index 0000000000000000000000000000000000000000..8fb2cde82b7923cf5a8c8ab1fec863a860b06bfd --- /dev/null +++ b/os/sys/critical.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup sys + * @{ + * + * \defgroup critical Critical sections + * @{ + * + * Platform-independent functions for critical section entry and exit + */ +/*---------------------------------------------------------------------------*/ +#ifndef CRITICAL_H_ +#define CRITICAL_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "sys/memory-barrier.h" +#include "sys/int-master.h" + +#include <stdint.h> +/*---------------------------------------------------------------------------*/ +/** + * \brief Enter a critical section + * \return The status of the master interrupt before entering the critical + * + * This function will return the status of the master interrupt as it was + * before entering the critical section. + * + * The semantics of the return value are entirely platform-specific. The + * calling code should not try to determine whether the master interrupt was + * previously enabled/disabled by interpreting the return value of this + * function. The return value should only be used as an argument to + * critical_exit(). + */ +static inline int_master_status_t +critical_enter() +{ + int_master_status_t status = int_master_read_and_disable(); + memory_barrier(); + return status; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Exit a critical section and restore the master interrupt + * \param status The new status of the master interrupt + * + * The semantics of \e status are platform-dependent. Normally, the argument + * provided to this function will be a value previously retrieved through a + * call to critical_enter(). + */ +static inline void +critical_exit(int_master_status_t status) +{ + memory_barrier(); + int_master_status_set(status); +} +/*---------------------------------------------------------------------------*/ +#endif /* CRITICAL_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/os/sys/ctimer.c b/os/sys/ctimer.c index 66698a8e642937fb011fac6e9ebb5d7c090a2023..1d628677bbf09947cd3a4a19064528ad8d7da59f 100644 --- a/os/sys/ctimer.c +++ b/os/sys/ctimer.c @@ -106,7 +106,7 @@ void ctimer_set_with_process(struct ctimer *c, clock_time_t t, void (*f)(void *), void *ptr, struct process *p) { - PRINTF("ctimer_set %p %u\n", c, (unsigned)t); + PRINTF("ctimer_set %p %lu\n", c, (unsigned long)t); c->p = p; c->f = f; c->ptr = ptr; diff --git a/os/sys/etimer.h b/os/sys/etimer.h index 59f665d10c7fe02c5d9685d353d00fc49cf4d1c4..02ad5df11f169d35468302996a368283e4def60a 100644 --- a/os/sys/etimer.h +++ b/os/sys/etimer.h @@ -94,7 +94,7 @@ struct etimer { * process that called the etimer_set() function. * */ -CCIF void etimer_set(struct etimer *et, clock_time_t interval); +void etimer_set(struct etimer *et, clock_time_t interval); /** * \brief Reset an event timer with the same interval as was @@ -111,7 +111,7 @@ CCIF void etimer_set(struct etimer *et, clock_time_t interval); * * \sa etimer_restart() */ -CCIF void etimer_reset(struct etimer *et); +void etimer_reset(struct etimer *et); /** * \brief Reset an event timer with a new interval. @@ -192,7 +192,7 @@ clock_time_t etimer_start_time(struct etimer *et); * This function tests if an event timer has expired and * returns true or false depending on its status. */ -CCIF int etimer_expired(struct etimer *et); +int etimer_expired(struct etimer *et); /** * \brief Stop a pending event timer. diff --git a/os/sys/int-master.h b/os/sys/int-master.h new file mode 100644 index 0000000000000000000000000000000000000000..1334abb1f32208454b2753275dfab4fde64e3b9a --- /dev/null +++ b/os/sys/int-master.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** \addtogroup sys + * @{ + * + * \defgroup interrupts Master interrupt manipulation + * @{ + * + * These functions can be used to manipulate the master interrupt in a + * platform-independent fashion + */ +/*---------------------------------------------------------------------------*/ +#ifndef INT_MASTER_H_ +#define INT_MASTER_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include <stdbool.h> +#include <stdint.h> +/*---------------------------------------------------------------------------*/ +#ifdef INT_MASTER_CONF_STATUS_DATATYPE +#define INT_MASTER_STATUS_DATATYPE INT_MASTER_CONF_STATUS_DATATYPE +#else +#define INT_MASTER_STATUS_DATATYPE uint32_t +#endif + +/** + * \brief Master interrupt state representation data type + * + * It is possible for the platform code to change this datatype by defining + * INT_MASTER_CONF_STATUS_DATATYPE + */ +typedef INT_MASTER_STATUS_DATATYPE int_master_status_t; +/*---------------------------------------------------------------------------*/ +/** + * \brief Enable the master interrupt + * + * The platform developer must provide this function + */ +void int_master_enable(void); + +/** + * \brief Disable the master interrupt + * \return The status of the master interrupt before disabling it + * + * This function will return the status of the master interrupt as it was + * before it got disabled. + * + * The semantics of the return value are entirely platform-specific. The + * calling code should not try to determine whether the master interrupt was + * previously enabled/disabled by interpreting the return value of this + * function. The return value should only be used as an argument to + * int_master_status_set() + * + * To determine the status of the master interrupt in a platform-independent + * fashion you should use int_master_is_enabled(). + * + * The platform developer must provide this function + */ +int_master_status_t int_master_read_and_disable(void); + +/** + * \brief Set the status of the master interrupt + * \param status The new status + * + * The semantics of \e status are platform-dependent. Normally, the argument + * provided to this function will be a value previously retrieved through a + * call to int_master_read_and_disable() + * + * The platform developer must provide this function + */ +void int_master_status_set(int_master_status_t status); + +/** + * \brief Retrieve the status of the master interrupt + * \retval false Interrupts are disabled + * \retval true Interrupts are enabled + * + * This function can be used to retrieve the status of the master interrupt + * in a platform-independent fashion. + * + * The platform developer must provide this function + */ +bool int_master_is_enabled(void); +/*---------------------------------------------------------------------------*/ +#endif /* INT_MASTER_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/os/sys/log-conf.h b/os/sys/log-conf.h index 209d3d1adec12432524fc82d6e60800284340229..24cf21f7185f404aeda78cb8281a042a65884eaa 100644 --- a/os/sys/log-conf.h +++ b/os/sys/log-conf.h @@ -81,6 +81,22 @@ #define LOG_OUTPUT(...) printf(__VA_ARGS__) #endif /* LOG_CONF_OUTPUT */ +/* + * Custom output function to prefix logs with level and module. + * + * This will only be called when LOG_CONF_WITH_MODULE_PREFIX is enabled and + * all implementations should be based on LOG_OUTPUT. + * + * \param level The log level + * \param levelstr The log level as string + * \param module The module string descriptor + */ +#ifdef LOG_CONF_OUTPUT_PREFIX +#define LOG_OUTPUT_PREFIX(level, levelstr, module) LOG_CONF_OUTPUT_PREFIX(level, levelstr, module) +#else /* LOG_CONF_OUTPUT_PREFIX */ +#define LOG_OUTPUT_PREFIX(level, levelstr, module) LOG_OUTPUT("[%-4s: %-10s] ", levelstr, module) +#endif /* LOG_CONF_OUTPUT_PREFIX */ + /******************************************************************************/ /********************* A list of currently supported modules ******************/ /******************************************************************************/ @@ -117,6 +133,14 @@ #define LOG_CONF_LEVEL_6TOP LOG_LEVEL_NONE #endif /* LOG_CONF_LEVEL_6TOP */ +#ifndef LOG_CONF_LEVEL_COAP +#define LOG_CONF_LEVEL_COAP LOG_LEVEL_NONE +#endif /* LOG_CONF_LEVEL_COAP */ + +#ifndef LOG_CONF_LEVEL_LWM2M +#define LOG_CONF_LEVEL_LWM2M LOG_LEVEL_NONE +#endif /* LOG_CONF_LEVEL_LWM2M */ + #ifndef LOG_CONF_LEVEL_MAIN #define LOG_CONF_LEVEL_MAIN LOG_LEVEL_INFO #endif /* LOG_CONF_LEVEL_MAIN */ diff --git a/os/sys/log.c b/os/sys/log.c index d4b21639dc5cfde43595f27fd50d5bf781e4f1fe..90709ec5f2041c369da280a8e197c956b114ab97 100644 --- a/os/sys/log.c +++ b/os/sys/log.c @@ -59,6 +59,8 @@ int curr_log_level_nullnet = LOG_CONF_LEVEL_NULLNET; int curr_log_level_mac = LOG_CONF_LEVEL_MAC; int curr_log_level_framer = LOG_CONF_LEVEL_FRAMER; int curr_log_level_6top = LOG_CONF_LEVEL_6TOP; +int curr_log_level_coap = LOG_CONF_LEVEL_COAP; +int curr_log_level_lwm2m = LOG_CONF_LEVEL_LWM2M; int curr_log_level_main = LOG_CONF_LEVEL_MAIN; struct log_module all_modules[] = { @@ -70,6 +72,8 @@ struct log_module all_modules[] = { {"mac", &curr_log_level_mac, LOG_CONF_LEVEL_MAC}, {"framer", &curr_log_level_framer, LOG_CONF_LEVEL_FRAMER}, {"6top", &curr_log_level_6top, LOG_CONF_LEVEL_6TOP}, + {"coap", &curr_log_level_coap, LOG_CONF_LEVEL_COAP}, + {"lwm2m", &curr_log_level_lwm2m, LOG_CONF_LEVEL_LWM2M}, {"main", &curr_log_level_main, LOG_CONF_LEVEL_MAIN}, {NULL, NULL, 0}, }; diff --git a/os/sys/log.h b/os/sys/log.h index d638bee7d1efc05c3ed71a7f3d21dad3bd43c954..e27a3007e03d8a52d0c23ec8d41a2b1d5bcf52a9 100644 --- a/os/sys/log.h +++ b/os/sys/log.h @@ -81,6 +81,8 @@ extern int curr_log_level_nullnet; extern int curr_log_level_mac; extern int curr_log_level_framer; extern int curr_log_level_6top; +extern int curr_log_level_coap; +extern int curr_log_level_lwm2m; extern int curr_log_level_main; extern struct log_module all_modules[]; @@ -93,6 +95,8 @@ extern struct log_module all_modules[]; #define LOG_LEVEL_MAC MIN((LOG_CONF_LEVEL_MAC), curr_log_level_mac) #define LOG_LEVEL_FRAMER MIN((LOG_CONF_LEVEL_FRAMER), curr_log_level_framer) #define LOG_LEVEL_6TOP MIN((LOG_CONF_LEVEL_6TOP), curr_log_level_6top) +#define LOG_LEVEL_COAP MIN((LOG_CONF_LEVEL_COAP), curr_log_level_coap) +#define LOG_LEVEL_LWM2M MIN((LOG_CONF_LEVEL_LWM2M), curr_log_level_lwm2m) #define LOG_LEVEL_MAIN MIN((LOG_CONF_LEVEL_MAIN), curr_log_level_main) /* Main log function */ @@ -101,7 +105,7 @@ extern struct log_module all_modules[]; if(level <= (LOG_LEVEL)) { \ if(newline) { \ if(LOG_WITH_MODULE_PREFIX) { \ - LOG_OUTPUT("[%-4s: %-10s] ", levelstr, LOG_MODULE); \ + LOG_OUTPUT_PREFIX(level, levelstr, LOG_MODULE); \ } \ if(LOG_WITH_LOC) { \ LOG_OUTPUT("[%s: %d] ", __FILE__, __LINE__); \ @@ -141,31 +145,40 @@ extern struct log_module all_modules[]; } while (0) /* More compact versions of LOG macros */ +#define LOG_PRINT(...) LOG(1, 0, "PRI", __VA_ARGS__) #define LOG_ERR(...) LOG(1, LOG_LEVEL_ERR, "ERR", __VA_ARGS__) #define LOG_WARN(...) LOG(1, LOG_LEVEL_WARN, "WARN", __VA_ARGS__) #define LOG_INFO(...) LOG(1, LOG_LEVEL_INFO, "INFO", __VA_ARGS__) #define LOG_DBG(...) LOG(1, LOG_LEVEL_DBG, "DBG", __VA_ARGS__) +#define LOG_PRINT_(...) LOG(0, 0, "PRI", __VA_ARGS__) #define LOG_ERR_(...) LOG(0, LOG_LEVEL_ERR, "ERR", __VA_ARGS__) #define LOG_WARN_(...) LOG(0, LOG_LEVEL_WARN, "WARN", __VA_ARGS__) #define LOG_INFO_(...) LOG(0, LOG_LEVEL_INFO, "INFO", __VA_ARGS__) #define LOG_DBG_(...) LOG(0, LOG_LEVEL_DBG, "DBG", __VA_ARGS__) +#define LOG_PRINT_LLADDR(...) LOG_LLADDR(0, __VA_ARGS__) #define LOG_ERR_LLADDR(...) LOG_LLADDR(LOG_LEVEL_ERR, __VA_ARGS__) #define LOG_WARN_LLADDR(...) LOG_LLADDR(LOG_LEVEL_WARN, __VA_ARGS__) #define LOG_INFO_LLADDR(...) LOG_LLADDR(LOG_LEVEL_INFO, __VA_ARGS__) #define LOG_DBG_LLADDR(...) LOG_LLADDR(LOG_LEVEL_DBG, __VA_ARGS__) +#define LOG_PRINT_6ADDR(...) LOG_6ADDR(0, __VA_ARGS__) #define LOG_ERR_6ADDR(...) LOG_6ADDR(LOG_LEVEL_ERR, __VA_ARGS__) #define LOG_WARN_6ADDR(...) LOG_6ADDR(LOG_LEVEL_WARN, __VA_ARGS__) #define LOG_INFO_6ADDR(...) LOG_6ADDR(LOG_LEVEL_INFO, __VA_ARGS__) #define LOG_DBG_6ADDR(...) LOG_6ADDR(LOG_LEVEL_DBG, __VA_ARGS__) -/* For testing log level */ -#define LOG_ERR_ENABLED (MIN(LOG_LEVEL, curr_log_level) >= LOG_LEVEL_ERR) -#define LOG_WARN_ENABLED (MIN(LOG_LEVEL, curr_log_level) >= LOG_LEVEL_WARN) -#define LOG_INFO_ENABLED (MIN(LOG_LEVEL, curr_log_level) >= LOG_LEVEL_INFO) -#define LOG_DBG_ENABLED (MIN(LOG_LEVEL, curr_log_level) >= LOG_LEVEL_DBG) +/* For checking log level. + As this builds on curr_log_level variables, this should not be used + in pre-processor macros. Use in a C 'if' statement instead, e.g.: + if(LOG_INFO_ENABLED) { ... } + Note that most compilers will still be able to strip the code out + for low enough log levels configurations. */ +#define LOG_ERR_ENABLED ((LOG_LEVEL) >= LOG_LEVEL_ERR) +#define LOG_WARN_ENABLED ((LOG_LEVEL) >= LOG_LEVEL_WARN) +#define LOG_INFO_ENABLED ((LOG_LEVEL) >= LOG_LEVEL_INFO) +#define LOG_DBG_ENABLED ((LOG_LEVEL) >= LOG_LEVEL_DBG) #if NETSTACK_CONF_WITH_IPV6 diff --git a/os/sys/memory-barrier.h b/os/sys/memory-barrier.h new file mode 100644 index 0000000000000000000000000000000000000000..a89b4384b93565cbec9452d0d01f776c333894cd --- /dev/null +++ b/os/sys/memory-barrier.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup sys + * @{ + * + * \defgroup memory-barrier CPU/Compiler memory barriers + * @{ + * + * API for CPU/Compiler memory barriers + */ +/*---------------------------------------------------------------------------*/ +#ifndef MEMORY_BARRIER_H_ +#define MEMORY_BARRIER_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +/*---------------------------------------------------------------------------*/ +#ifdef MEMORY_BARRIER_CONF_ARCH_HEADER_PATH +#include MEMORY_BARRIER_CONF_ARCH_HEADER_PATH +#endif /* MEMORY_BARRIER_CONF_ARCH_HEADER_PATH */ +/*---------------------------------------------------------------------------*/ +#ifndef memory_barrier +/** + * \brief Insert a memory barrier + * + * It is the platform/CPU developer's responsibility to expand this macro to + * a function that creates a memory barrier. Calling this macro will otherwise + * not generate any code. + */ +#define memory_barrier() +#endif +/*---------------------------------------------------------------------------*/ +#endif /* MEMORY_BARRIER_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/os/sys/mt.c b/os/sys/mt.c deleted file mode 100644 index d5bc103989d9f9d8499c3bfd5ae40d2e3d113826..0000000000000000000000000000000000000000 --- a/os/sys/mt.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2006, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - * Author: Adam Dunkels <adam@sics.se> - * - */ - -/** - * \file - * Implementation of the archtecture agnostic parts of the preemptive - * multithreading library for Contiki. - * - * \author - * Adam Dunkels <adam@sics.se> - * - */ - -#include "contiki.h" -#include "sys/mt.h" -#include "sys/cc.h" - -static struct mt_thread *current; - -/*--------------------------------------------------------------------------*/ -void -mt_init(void) -{ - mtarch_init(); -} -/*--------------------------------------------------------------------------*/ -void -mt_remove(void) -{ - mtarch_remove(); -} -/*--------------------------------------------------------------------------*/ -void -mt_start(struct mt_thread *thread, void (* function)(void *), void *data) -{ - /* Call the architecture dependant function to set up the processor - stack with the correct parameters. */ - mtarch_start(&thread->thread, function, data); - - thread->state = MT_STATE_STARTED; -} -/*--------------------------------------------------------------------------*/ -void -mt_exec(struct mt_thread *thread) -{ - if(thread->state == MT_STATE_STARTED) { - current = thread; - /* Switch context to the thread. The function call will not return - until the the thread has yielded, or is preempted. */ - mtarch_exec(&thread->thread); - } -} -/*--------------------------------------------------------------------------*/ -void -mt_yield(void) -{ - mtarch_pstop(); - /* This function is called from the running thread, and we call the - switch function in order to switch the thread to the main Contiki - program instead. For us, the switch function will not return - until the next time we are scheduled to run. */ - mtarch_yield(); -} -/*--------------------------------------------------------------------------*/ -void -mt_exit(void) -{ - mtarch_pstop(); - current->state = MT_STATE_EXITED; - mtarch_yield(); -} -/*--------------------------------------------------------------------------*/ -void -mt_stop(struct mt_thread *thread) -{ - mtarch_stop(&thread->thread); -} -/*--------------------------------------------------------------------------*/ diff --git a/os/sys/mt.h b/os/sys/mt.h deleted file mode 100644 index abe04d12e71fded3177fbcb13ee5ebc49e508061..0000000000000000000000000000000000000000 --- a/os/sys/mt.h +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (c) 2004, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - * Author: Adam Dunkels <adam@sics.se> - * - */ - -/** \addtogroup threads - * @{ - */ - -/** - * \defgroup mt Multi-threading library - * - * The event driven Contiki kernel does not provide multi-threading - * by itself - instead, preemptive multi-threading is implemented - * as a library that optionally can be linked with applications. This - * library consists of two parts: a platform independent part, which is - * the same for all platforms on which Contiki runs, and a platform - * specific part, which must be implemented specifically for the - * platform that the multi-threading library should run. - * @{ - * - * The Contiki multi-threading library requires some architecture - * specific support for setting up and switching stacks. This support - * requires four stack manipulation functions to be implemented: - * mtarch_start(), which sets up the stack frame for a new thread, - * mtarch_exec(), which switches in the stack of a thread, - * mtarch_yield(), which restores the kernel stack from a thread's - * stack and mtarch_stop(), which cleans up the stack of a thread. - * Additionally, two functions for controlling the preemption - * (if any) must be implemented: mtarch_pstart() and mtarch_pstop(). - * If no preemption is used, these functions can be implemented as - * empty functions. Finally, the function mtarch_init() is called by - * mt_init(), and can be used for initialization of timer interrupts, - * or any other mechanisms required for correct operation of the - * architecture specific support functions while mtarch_remove() is - * called by mt_remove() to clean up those resources. - * - */ - -/** - * \file - * Header file for the preemptive multitasking library for Contiki. - * \author - * Adam Dunkels <adam@sics.se> - * - */ -#ifndef MT_H_ -#define MT_H_ - -#include "contiki.h" - -#define MT_STATE_STARTED 1 -#define MT_STATE_EXITED 2 - -/** - * An opaque structure that is used for holding the state of a thread. - * - * The structure should be defined in the "mtarch.h" file. This - * structure typically holds the entire stack for the thread. - */ -struct mtarch_thread; - -/** - * Initialize the architecture specific support functions for the - * multi-thread library. - * - * This function is implemented by the architecture specific functions - * for the multi-thread library and is called by the mt_init() - * function as part of the initialization of the library. The - * mtarch_init() function can be used for, e.g., starting preemption - * timers or other architecture specific mechanisms required for the - * operation of the library. - */ -void mtarch_init(void); - -/** - * Uninstall library and clean up. - * - */ -void mtarch_remove(void); - -/** - * Setup the stack frame for a thread that is being started. - * - * This function is called by the mt_start() function in order to set - * up the architecture specific stack of the thread to be started. - * - * \param thread A pointer to a struct mtarch_thread for the thread to - * be started. - * - * \param function A pointer to the function that the thread will - * start executing the first time it is scheduled to run. - * - * \param data A pointer to the argument that the function should be - * passed. - */ -void mtarch_start(struct mtarch_thread *thread, - void (* function)(void *data), - void *data); - -/** - * Start executing a thread. - * - * This function is called from mt_exec() and the purpose of the - * function is to start execution of the thread. The function should - * switch in the stack of the thread, and does not return until the - * thread has explicitly yielded (using mt_yield()) or until it is - * preempted. - * - * \param thread A pointer to a struct mtarch_thread for the thread to - * be executed. - * - */ -void mtarch_exec(struct mtarch_thread *thread); - -/** - * Yield the processor. - * - * This function is called by the mt_yield() function, which is called - * from the running thread in order to give up the processor. - * - */ -void mtarch_yield(void); - -/** - * Clean up the stack of a thread. - * - * This function is called by the mt_stop() function in order to clean - * up the architecture specific stack of the thread to be stopped. - * - * \note If the stack is wholly contained in struct mtarch_thread this - * function may very well be empty. - * - * \param thread A pointer to a struct mtarch_thread for the thread to - * be stopped. - * - */ -void mtarch_stop(struct mtarch_thread *thread); - -void mtarch_pstart(void); -void mtarch_pstop(void); - -/** @} */ - - -#include "mtarch.h" - -struct mt_thread { - int state; - struct mtarch_thread thread; -}; - -/** - * Initializes the multithreading library. - * - */ -void mt_init(void); - -/** - * Uninstalls library and cleans up. - * - */ -void mt_remove(void); - - -/** - * Starts a multithreading thread. - * - * \param thread Pointer to an mt_thread struct that must have been - * previously allocated by the caller. - * - * \param function A pointer to the entry function of the thread that is - * to be set up. - * - * \param data A pointer that will be passed to the entry function. - * - */ -void mt_start(struct mt_thread *thread, void (* function)(void *), void *data); - -/** - * Execute parts of a thread. - * - * This function is called by a Contiki process and runs a - * thread. The function does not return until the thread has yielded, - * or is preempted. - * - * \note The thread library must first be initialized with the mt_init() - * function. - * - * \param thread A pointer to a struct mt_thread block that must be - * allocated by the caller. - * - */ -void mt_exec(struct mt_thread *thread); - -/** - * Voluntarily give up the processor. - * - * This function is called by a running thread in order to give up - * control of the CPU. - * - */ -void mt_yield(void); - -/** - * Exit a thread. - * - * This function is called from within an executing thread in order to - * exit the thread. The function never returns. - * - */ -void mt_exit(void); - -/** - * Stop a thread. - * - * This function is called by a Contiki process in order to clean up a - * thread. The struct mt_thread block may then be discarded by the caller. - * - * \param thread A pointer to a struct mt_thread block that must be - * allocated by the caller. - * - */ -void mt_stop(struct mt_thread *thread); - -/** @} */ -#endif /* MT_H_ */ diff --git a/os/sys/mutex.c b/os/sys/mutex.c new file mode 100644 index 0000000000000000000000000000000000000000..54321f8e35f102d9f996f6dc038d1c53e4172add --- /dev/null +++ b/os/sys/mutex.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup mutex + * @{ + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "sys/mutex.h" +#include "sys/critical.h" + +#include <stdint.h> +#include <stdbool.h> +/*---------------------------------------------------------------------------*/ +bool +mutex_generic_try_lock(volatile mutex_t *mutex) +{ + bool success = false; + int_master_status_t status = critical_enter(); + + if(*mutex == MUTEX_STATUS_UNLOCKED) { + *mutex = MUTEX_STATUS_LOCKED; + success = true; + } + + critical_exit(status); + + return success; +} +/*---------------------------------------------------------------------------*/ +void +mutex_generic_unlock(volatile mutex_t *mutex) +{ + int_master_status_t status = critical_enter(); + + *mutex = MUTEX_STATUS_UNLOCKED; + + critical_exit(status); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/sys/mutex.h b/os/sys/mutex.h new file mode 100644 index 0000000000000000000000000000000000000000..6695acaa92d26c975bc17593aa685cc4a649b848 --- /dev/null +++ b/os/sys/mutex.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup sys + * @{ + * + * \defgroup mutex Mutexes + * @{ + * + * This library provides an API and generic implementation of mutexes. + * + * Calling code should manipulate mutexes through the mutex_try_lock() and + * mutex_unlock() macros. By default, those macros will expand to the generic + * mutex manipulation implementations provided here. While these will work, + * they do reply on disabling the master interrupt in order to perform the + * lock/unlock operation. + * + * It is possible to override those generic implementation with CPU-specific + * implementations that exploit synchronisation instructions. To do so, + * create a CPU-specific header file. In this file, define mutex_try_lock() + * and mutex_unlock() to expand to the respective CPU function names. These + * can (but do not have to) be inlined. Then define MUTEX_CONF_ARCH_HEADER_PATH + * as this header's filename. + */ +/*---------------------------------------------------------------------------*/ +#ifndef MUTEX_H_ +#define MUTEX_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include <stdint.h> +#include <stdbool.h> +/*---------------------------------------------------------------------------*/ +#define MUTEX_STATUS_LOCKED 1 /** The mutex is locked */ +#define MUTEX_STATUS_UNLOCKED 0 /** The mutex is not locked */ +/*---------------------------------------------------------------------------*/ +#ifdef MUTEX_CONF_ARCH_HEADER_PATH +#include MUTEX_CONF_ARCH_HEADER_PATH +#endif /* MUTEX_CONF_ARCH_HEADER_PATH */ +/*---------------------------------------------------------------------------*/ +#if !MUTEX_CONF_HAS_MUTEX_T +/** + * \brief Mutex data type + * + * It is possible for the platform to override this with its own typedef. In + * this scenario, make sure to also define MUTEX_CONF_HAS_MUTEX_T as 1. + */ +typedef uint_fast8_t mutex_t; +#endif +/*---------------------------------------------------------------------------*/ +#ifndef mutex_try_lock +/** + * \brief Try to lock a mutex + * \param m A pointer to the mutex to be locked + * \retval true Locking succeeded + * \retval false Locking failed (the mutex is already locked) + * + * This macro will expand to mutex_generic_try_lock() or to a CPU-provided + * implementation. Platform-independent code should use this macro instead + * of mutex_generic_try_lock(). + */ +#define mutex_try_lock(m) mutex_generic_try_lock(m) +#endif + +#ifndef mutex_unlock +/** + * \brief Unlock a previously acquired mutex + * \param m A pointer to the mutex to be unlocked + * + * This macro will expand to mutex_generic_unlock() or to a CPU-provided + * implementation. Platform-independent code should use this macro instead + * of mutex_generic_unlock(). + */ +#define mutex_unlock(m) mutex_generic_unlock(m) +#endif +/*---------------------------------------------------------------------------*/ +/** + * \brief Try to lock a mutex + * \param mutex A pointer to the mutex to be locked + * \retval true Locking succeeded + * \retval false Locking failed (the mutex is already locked) + * + * Do not call this function directly. Use the mutex_try_lock() macro instead. + */ +bool mutex_generic_try_lock(volatile mutex_t *mutex); + +/** + * \brief Unlock a previously acquired mutex + * \param mutex A pointer to the mutex to be unlocked + * + * Do not call this function directly. Use the mutex_unlock() macro instead. + */ +void mutex_generic_unlock(volatile mutex_t *mutex); +/*---------------------------------------------------------------------------*/ +#endif /* MUTEX_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/os/sys/process.h b/os/sys/process.h index bd206b6e7c17eb4f81eddb7a7e9a70e61f313ee1..5cffdb526295b718ebe768c509d61012eb2ee5b0 100644 --- a/os/sys/process.h +++ b/os/sys/process.h @@ -339,7 +339,7 @@ struct process { * process * */ -CCIF void process_start(struct process *p, process_data_t data); +void process_start(struct process *p, process_data_t data); /** * Post an asynchronous event. @@ -362,7 +362,7 @@ CCIF void process_start(struct process *p, process_data_t data); * \retval PROCESS_ERR_FULL The event queue was full and the event could * not be posted. */ -CCIF int process_post(struct process *p, process_event_t ev, process_data_t data); +int process_post(struct process *p, process_event_t ev, process_data_t data); /** * Post a synchronous event to a process. @@ -374,8 +374,8 @@ CCIF int process_post(struct process *p, process_event_t ev, process_data_t data * \param data A pointer to additional data that is posted together * with the event. */ -CCIF void process_post_synch(struct process *p, - process_event_t ev, process_data_t data); +void process_post_synch(struct process *p, + process_event_t ev, process_data_t data); /** * \brief Cause a process to exit @@ -387,7 +387,7 @@ CCIF void process_post_synch(struct process *p, * * \sa PROCESS_CURRENT() */ -CCIF void process_exit(struct process *p); +void process_exit(struct process *p); /** @@ -400,7 +400,7 @@ CCIF void process_exit(struct process *p); * \hideinitializer */ #define PROCESS_CURRENT() process_current -CCIF extern struct process *process_current; +extern struct process *process_current; /** * Switch context to another process @@ -450,7 +450,7 @@ process_current = p * \note There currently is no way to deallocate an allocated event * number. */ -CCIF process_event_t process_alloc_event(void); +process_event_t process_alloc_event(void); /** @} */ @@ -467,7 +467,7 @@ CCIF process_event_t process_alloc_event(void); * * \param p A pointer to the process' process structure. */ -CCIF void process_poll(struct process *p); +void process_poll(struct process *p); /** @} */ @@ -509,7 +509,7 @@ int process_run(void); * \retval Non-zero if the process is running. * \retval Zero if the process is not running. */ -CCIF int process_is_running(struct process *p); +int process_is_running(struct process *p); /** * Number of events waiting to be processed. @@ -521,7 +521,7 @@ int process_nevents(void); /** @} */ -CCIF extern struct process *process_list; +extern struct process *process_list; #define PROCESS_LIST() process_list diff --git a/os/sys/stack-check.c b/os/sys/stack-check.c new file mode 100644 index 0000000000000000000000000000000000000000..61f8d98abb02de36876f36a6404ec8499cd1af66 --- /dev/null +++ b/os/sys/stack-check.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2017, University of Bristol - http://www.bris.ac.uk/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup stack + * @{ + */ + +/** + * \file + * Implementation of the stack checker library. + * \author + * Atis Elsts <atis.elsts@bristol.ac.uk> + */ + +#include "contiki.h" +#include "sys/stack-check.h" +#include "dev/watchdog.h" +#include <string.h> + +#include "sys/log.h" +#define LOG_MODULE "Stack" +#define LOG_LEVEL LOG_LEVEL_MAIN + +/*---------------------------------------------------------------------------*/ +/* linker will provide a symbol for the end of the .bss segment */ +extern uint8_t _stack; + +#if STACK_CHECK_PERIODIC_CHECKS +PROCESS(stack_check_process, "Stack check"); +#endif +/*---------------------------------------------------------------------------*/ +/* The symbol with which the stack memory is initially filled */ +#define STACK_FILL 0xcd +/*---------------------------------------------------------------------------*/ +#ifdef STACK_ORIGIN +/* use the #defined value */ +#define GET_STACK_ORIGIN() STACK_ORIGIN +#else +/* use the value provided by the linker script */ +extern int _stack_origin; +#define GET_STACK_ORIGIN() (&_stack_origin) +#endif +/*---------------------------------------------------------------------------*/ +void +stack_check_init(void) +{ + uint8_t *p; + + /* Make this static to avoid destroying it in the while loop */ + static void *stack_top; + /* Use address of this local variable as a boundary */ + stack_top = &p; + + /* Note: this is expected to be called before the WDT is started! */ + p = &_stack; + while(p < (uint8_t *)stack_top) { + *p++ = STACK_FILL; + } + +#if STACK_CHECK_PERIODIC_CHECKS + /* Start the periodic checker process */ + process_start(&stack_check_process, NULL); +#endif +} +/*---------------------------------------------------------------------------*/ +uint16_t +stack_check_get_usage(void) +{ + uint8_t *p = &_stack; + + /* Make sure WDT is not triggered */ + watchdog_periodic(); + + /* Skip the bytes used after heap; it's 1 byte by default for _stack, + * more than that means dynamic memory allocation is used somewhere. + */ + while(*p != STACK_FILL && p < (uint8_t *)GET_STACK_ORIGIN()) { + p++; + } + + /* Skip the region of the memory reserved for the stack not used yet by the program */ + while(*p == STACK_FILL && p < (uint8_t *)GET_STACK_ORIGIN()) { + p++; + } + + /* Make sure WDT is not triggered */ + watchdog_periodic(); + + if(p >= (uint8_t*)GET_STACK_ORIGIN()) { + /* This means the stack is screwed. */ + return 0xffff; + } + + return (uint8_t *)GET_STACK_ORIGIN() - p; +} +/*---------------------------------------------------------------------------*/ +uint16_t +stack_check_get_reserved_size(void) +{ + return (uint8_t *)GET_STACK_ORIGIN() - &_stack; +} +/*---------------------------------------------------------------------------*/ +#if STACK_CHECK_PERIODIC_CHECKS +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(stack_check_process, ev, data) +{ + static struct etimer et; + + PROCESS_BEGIN(); + + etimer_set(&et, STACK_CHECK_PERIOD); + + while(1) { + uint16_t actual, allowed; + + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + actual = stack_check_get_usage(); + allowed = stack_check_get_reserved_size(); + if(actual > allowed) { + LOG_ERR("Check failed: %u vs. %u\n", actual, allowed); + } else { + LOG_DBG("Check ok: %u vs. %u\n", actual, allowed); + } + + etimer_reset(&et); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +#endif /* STACK_CHECK_PERIODIC_CHECKS */ +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/os/sys/stack-check.h b/os/sys/stack-check.h new file mode 100644 index 0000000000000000000000000000000000000000..805c4b7da6e6b229abd0de4a5e9d6b641f2cb030 --- /dev/null +++ b/os/sys/stack-check.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2017, University of Bristol - http://www.bris.ac.uk/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \file + * Stack checker library header file. + * \author + * Atis Elsts <atis.elsts@bristol.ac.uk> + */ + +/** \addtogroup sys + * @{ */ + +/** + * \defgroup stack Stack checker library + * + * Basic support for stack guards and stack overflow detection. + * On startup, fills the area between the stack and the heap with a known pattern. + * During execution, the fill can be checked in order to find out + * the extent to which the stack has been used. + * + * @{ + */ + +#ifndef STACK_CHECK_H_ +#define STACK_CHECK_H_ + +#include "contiki-conf.h" + +/* Determine whether stack checking is supported depending on the plaform. */ +#ifdef PLATFORM_CONF_SUPPORTS_STACK_CHECK +#if !PLATFORM_CONF_SUPPORTS_STACK_CHECK +/* Stack checker cannot be enabled, since the platform does not support it */ +#undef STACK_CHECK_CONF_ENABLED +#define STACK_CHECK_CONF_ENABLED 0 +#endif /* !PLATFORM_CONF_SUPPORTS_STACK_CHECK */ +#endif /* ifdef PLATFORM_CONF_SUPPORTS_STACK_CHECK */ + +/* If this is disabled, the functions are no-ops */ +#ifdef STACK_CHECK_CONF_ENABLED +#define STACK_CHECK_ENABLED STACK_CHECK_CONF_ENABLED +#else +#define STACK_CHECK_ENABLED 1 /* Enable by default */ +#endif + +/* Perform periodic stack integrity checks? */ +#ifdef STACK_CHECK_CONF_PERIODIC_CHECKS +#define STACK_CHECK_PERIODIC_CHECKS STACK_CHECK_CONF_PERIODIC_CHECKS +#else +#define STACK_CHECK_PERIODIC_CHECKS 1 /* Enable by default */ +#endif + +/* How often to do the periodic integrity checks, if enabled? */ +#ifdef STACK_CHECK_CONF_PERIOD +#define STACK_CHECK_PERIOD STACK_CHECK_CONF_PERIOD +#else +#define STACK_CHECK_PERIOD (10 * CLOCK_SECOND) +#endif + +/** + * \brief Initialize the stack area with a known pattern + * + * This function initializes the memory between the stack and heap + * areas. The function should be called by the system + * during boot-up. + */ +void stack_check_init(void); + +/** + * \brief Calculate the maximal stack usage so far. + * + * This function relies on the assumption that the stack memory + * that has been reserved by functions and local variables + * is actually overwritten with new contents. If the stack is + * just reserved, but not used, the function will fail to detect + * that usage. + * In addition, this function can warn if the stack memory range + * has been completely used, but it cannot detect + * and warn if stack overflow has already taken place. + */ +uint16_t stack_check_get_usage(void); + +/** + * \brief Calculate the maximal permitted stack usage. + * + * This function returns the number of bytes between the origin + * of the stack and the end of heap. + */ +uint16_t stack_check_get_reserved_size(void); + +/** + * \brief The origin point from which the stack grows (an optional #define) + * + */ +#ifdef STACK_CONF_ORIGIN +#define STACK_ORIGIN STACK_CONF_ORIGIN +#endif + +#endif /* STACK_CHECK_H_ */ + +/** @} */ +/** @} */ diff --git a/os/sys/timer.h b/os/sys/timer.h index b05963e479a9a365a581bea700629c9dd567adaa..54abcb3c2168c3c1e21ed6428332fe0c42a3fd58 100644 --- a/os/sys/timer.h +++ b/os/sys/timer.h @@ -84,10 +84,10 @@ struct timer { clock_time_t interval; }; -CCIF void timer_set(struct timer *t, clock_time_t interval); +void timer_set(struct timer *t, clock_time_t interval); void timer_reset(struct timer *t); void timer_restart(struct timer *t); -CCIF int timer_expired(struct timer *t); +int timer_expired(struct timer *t); clock_time_t timer_remaining(struct timer *t); diff --git a/tests/00-doxygen/Makefile b/tests/00-doxygen/Makefile index ba3600b79c9e9e11b1ad6934a07719f64fab774f..3d99c5d009cd13bcfe02f3541889b606fc2e19f8 100644 --- a/tests/00-doxygen/Makefile +++ b/tests/00-doxygen/Makefile @@ -27,31 +27,32 @@ DOCDIR=../../tools/doxygen -all: summary +all: clean summary doxygen: - @make -C $(DOCDIR) 2> doxygen.runerr > doxygen.runlog + @make -C $(DOCDIR) 2> doxygen.err > /dev/null summary: doxygen @( \ 1> summary; \ - if [ -s doxygen.runerr ] ; then \ - echo "doxygen: FAIL ಠ_ಠ\nDoxygen caused some errors. Please fix these." >> summary; \ - echo "Errors:" >> summary; \ - cat doxygen.runerr >> summary; \ - echo >> summary; \ + if [ -s doxygen.err ] ; then \ + echo "Doxygen: TEST FAIL" | tee summary; \ + echo "Errors:"; \ + cat doxygen.err; \ fi ; \ if [ -s $(DOCDIR)/doxygen.log ] ; then \ - echo "doxygen: FAIL ಠ_ಠ\nDoxygen caused some warnings. Please fix these." >> summary; \ - echo "Warnings:" >> summary; \ - cat $(DOCDIR)/doxygen.log >> summary; \ + echo "Doxygen: TEST FAIL" | tee summary; \ + echo "Warnings:"; \ + cat $(DOCDIR)/doxygen.log; \ fi ; \ if [ ! -s summary ] ; then \ - echo "doxygen: OK\nDoxygen found no warnings" >> summary; \ + echo "Doxygen: TEST OK (no warning nor error)" | tee summary; \ fi ; \ - cat summary \ ) + @rm doxygen.err + @echo "========== Summary ==========" + @cat summary clean: - @rm -f summary doxygen.runlog doxygen.runerr + @rm -f summary doxygen.err @make -C $(DOCDIR) clean diff --git a/tests/01-compile-base/Makefile b/tests/01-compile-base/Makefile index b02e202cd28977711b3b752358bf2a05c3371b66..67346c086714999b087d375792c0ab770eb457fc 100644 --- a/tests/01-compile-base/Makefile +++ b/tests/01-compile-base/Makefile @@ -3,16 +3,30 @@ TOOLSDIR=../../tools EXAMPLES = \ hello-world/native \ +hello-world/native:MAKE_NET=MAKE_NET_NULLNET \ +hello-world/native:MAKE_ROUTING=MAKE_ROUTING_RPL_CLASSIC \ hello-world/sky \ storage/eeprom-test/native \ multicast/sky \ libs/logging/native \ libs/energest/native \ libs/energest/sky \ +libs/data-structures/native \ +libs/data-structures/sky \ +libs/stack-check/sky \ +lwm2m-ipso-objects/native \ +lwm2m-ipso-objects/native:MAKE_WITH_DTLS=1 \ rpl-udp/sky \ rpl-border-router/native \ +rpl-border-router/native:MAKE_ROUTING=MAKE_ROUTING_RPL_CLASSIC \ rpl-border-router/sky \ slip-radio/sky \ +libs/ipv6-hooks/sky \ +nullnet/native \ +mqtt-client/native \ +coap/coap-example-client/native \ +coap/coap-example-server/native \ +coap/coap-plugtest-server/native \ TOOLS= diff --git a/tests/02-compile-arm-ports-01/Makefile b/tests/02-compile-arm-ports-01/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..5e73c4ecbcf8d7c4b0be0175133102868a056b34 --- /dev/null +++ b/tests/02-compile-arm-ports-01/Makefile @@ -0,0 +1,66 @@ +EXAMPLESDIR=../../examples +TOOLSDIR=../../tools + +EXAMPLES = \ +platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx \ +platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:MAKE_ROUTING=MAKE_ROUTING_RPL_CLASSIC \ +platform-specific/cc26xx/very-sleepy-demo/srf06-cc26xx:BOARD=sensortag/cc2650 \ +platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=sensortag/cc2650 \ +platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=sensortag/cc1350 \ +platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=srf06/cc13xx \ +platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=launchpad/cc2650 \ +platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=launchpad/cc1310 \ +platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=launchpad/cc1350 \ +platform-specific/cc26xx/very-sleepy-demo/srf06-cc26xx \ +platform-specific/cc26xx/ble-ipv6/srf06-cc26xx:BOARD=sensortag/cc2650 \ +nullnet/srf06-cc26xx:BOARD=sensortag/cc2650 \ +rpl-border-router/srf06-cc26xx:BOARD=launchpad/cc2650 \ +sensniff/srf06-cc26xx \ +sensniff/srf06-cc26xx:BOARD=launchpad/cc1310 \ +dev/gpio-hal/srf06-cc26xx:BOARD=srf06/cc13xx \ +dev/gpio-hal/srf06-cc26xx:BOARD=srf06/cc26xx \ +dev/gpio-hal/srf06-cc26xx:BOARD=sensortag/cc1350 \ +dev/gpio-hal/srf06-cc26xx:BOARD=sensortag/cc2650 \ +dev/gpio-hal/srf06-cc26xx:BOARD=launchpad/cc1310 \ +dev/gpio-hal/srf06-cc26xx:BOARD=launchpad/cc1350 \ +dev/gpio-hal/srf06-cc26xx:BOARD=launchpad/cc2650 \ +dev/leds/srf06-cc26xx:BOARD=srf06/cc13xx \ +dev/leds/srf06-cc26xx:BOARD=srf06/cc26xx \ +dev/leds/srf06-cc26xx:BOARD=sensortag/cc1350 \ +dev/leds/srf06-cc26xx:BOARD=sensortag/cc2650 \ +dev/leds/srf06-cc26xx:BOARD=launchpad/cc1310 \ +dev/leds/srf06-cc26xx:BOARD=launchpad/cc1350 \ +dev/leds/srf06-cc26xx:BOARD=launchpad/cc2650 \ +6tisch/etsi-plugtest-2017/srf06-cc26xx:BOARD=launchpad/cc2650 \ +mqtt-client/srf06-cc26xx:BOARD=srf06/cc26xx \ +mqtt-client/srf06-cc26xx:BOARD=launchpad/cc2650 \ +mqtt-client/srf06-cc26xx:BOARD=sensortag/cc2650 \ +mqtt-client/cc2538dk \ +storage/cfs-coffee/cc2538dk \ +sensniff/cc2538dk \ +rpl-udp/cc2538dk \ +coap/coap-example-client/cc2538dk \ +coap/coap-example-server/cc2538dk \ +slip-radio/cc2538dk \ +lwm2m-ipso-objects/cc2538dk \ +multicast/cc2538dk \ +dev/gpio-hal/cc2538dk \ +dev/leds/cc2538dk \ +platform-specific/cc2538-common/cc2538dk \ +platform-specific/cc2538-common/crypto/cc2538dk \ +platform-specific/cc2538-common/pka/cc2538dk \ +hello-world/cc2538dk \ +rpl-border-router/cc2538dk \ +rpl-border-router/cc2538dk:MAKE_ROUTING=MAKE_ROUTING_RPL_CLASSIC \ +hello-world/nrf52dk \ +platform-specific/nrf52dk/coap-demo/coap-server/nrf52dk \ +platform-specific/nrf52dk/coap-demo/coap-client/nrf52dk:SERVER_IPV6_EP=ffff \ +platform-specific/nrf52dk/mqtt-demo/nrf52dk \ +platform-specific/nrf52dk/blink-hello/nrf52dk \ +platform-specific/nrf52dk/timer-test/nrf52dk \ +libs/data-structures/nrf52dk \ +libs/logging/nrf52dk + +TOOLS= + +include ../Makefile.compile-test diff --git a/tests/02-compile-arm-ports/Makefile b/tests/02-compile-arm-ports/Makefile deleted file mode 100644 index 78487d7542bdea89e48511b03676e0478cd9cead..0000000000000000000000000000000000000000 --- a/tests/02-compile-arm-ports/Makefile +++ /dev/null @@ -1,63 +0,0 @@ -EXAMPLESDIR=../../examples -TOOLSDIR=../../tools - -EXAMPLES = \ -platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx \ -platform-specific/cc26xx/very-sleepy-demo/srf06-cc26xx:BOARD=sensortag/cc2650 \ -platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=sensortag/cc2650 \ -platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=sensortag/cc1350 \ -platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=srf06/cc13xx \ -platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=launchpad/cc2650 \ -platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=launchpad/cc1310 \ -platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=launchpad/cc1350 \ -platform-specific/cc26xx/very-sleepy-demo/srf06-cc26xx \ -hello-world/cc2538dk \ -rpl-border-router/cc2538dk \ -rpl-border-router/srf06-cc26xx:BOARD=launchpad/cc2650 \ -rpl-border-router/zoul \ -rpl-udp/cc2538dk \ -coap/cc2538dk \ -slip-radio/cc2538dk \ -ipso-objects/cc2538dk \ -multicast/cc2538dk \ -platform-specific/cc2538-common/cc2538dk \ -platform-specific/cc2538-common/mqtt-demo/cc2538dk \ -platform-specific/cc2538-common/crypto/cc2538dk \ -platform-specific/cc2538-common/pka/cc2538dk \ -platform-specific/cc2538-common/zoul \ -platform-specific/cc2538-common/mqtt-demo/zoul \ -platform-specific/cc2538-common/crypto/zoul \ -platform-specific/cc2538-common/pka/zoul \ -platform-specific/zoul/orion/ip64-router/zoul:BOARD=orion \ -coap/zoul \ -ipso-objects/zoul \ -hello-world/zoul \ -sensniff/cc2538dk \ -sensniff/openmote-cc2538 \ -sensniff/zoul \ -sensniff/zoul:ZOUL_CONF_SUB_GHZ_SNIFFER=1 \ -sensniff/srf06-cc26xx \ -sensniff/srf06-cc26xx:BOARD=launchpad/cc1310 \ -storage/cfs-coffee/cc2538dk \ -storage/cfs-coffee/openmote-cc2538 \ -storage/cfs-coffee/zoul \ -storage/antelope-shell/zoul \ -6tisch/simple-node/zoul \ -6tisch/simple-node/zoul:MAKE_WITH_ORCHESTRA=1 \ -6tisch/simple-node/zoul:MAKE_WITH_SECURITY=1 \ -libs/logging/zoul \ -6tisch/etsi-plugtest-2017/zoul:BOARD=remote \ -6tisch/etsi-plugtest-2017/srf06-cc26xx:BOARD=launchpad/cc2650 \ -6tisch/6p-packet/zoul \ -6tisch/sixtop/zoul \ -http-socket/zoul \ -libs/timers/zoul \ -libs/energest/zoul \ -libs/trickle-library/zoul \ -nullnet/zoul \ -slip-radio/zoul \ - - -TOOLS= - -include ../Makefile.compile-test diff --git a/tests/03-compile-arm-ports-02/Makefile b/tests/03-compile-arm-ports-02/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..db016afaaa56be6272e5de3b5699adb939affabf --- /dev/null +++ b/tests/03-compile-arm-ports-02/Makefile @@ -0,0 +1,67 @@ +EXAMPLESDIR=../../examples +TOOLSDIR=../../tools + +EXAMPLES = \ +rpl-border-router/zoul \ +platform-specific/cc2538-common/zoul \ +platform-specific/cc2538-common/crypto/zoul \ +platform-specific/cc2538-common/pka/zoul \ +platform-specific/zoul/orion/ip64-router/zoul:BOARD=orion \ +platform-specific/zoul/orion/client/zoul:BOARD=orion \ +platform-specific/zoul/rev-b/zoul:BOARD=remote-revb \ +platform-specific/zoul/at-test/zoul \ +platform-specific/zoul/rtcc/zoul \ +platform-specific/zoul/zoul \ +coap/coap-example-client/zoul \ +coap/coap-example-server/zoul \ +multicast/zoul \ +lwm2m-ipso-objects/zoul \ +lwm2m-ipso-objects/zoul:MAKE_WITH_DTLS=1 \ +hello-world/zoul \ +sensniff/zoul \ +sensniff/zoul:ZOUL_CONF_SUB_GHZ_SNIFFER=1 \ +storage/cfs-coffee/zoul \ +storage/antelope-shell/zoul \ +6tisch/simple-node/zoul \ +6tisch/simple-node/zoul:MAKE_WITH_ORCHESTRA=1 \ +6tisch/simple-node/zoul:MAKE_WITH_SECURITY=1 \ +libs/logging/zoul \ +6tisch/etsi-plugtest-2017/zoul:BOARD=remote \ +6tisch/6p-packet/zoul \ +6tisch/sixtop/zoul \ +websocket/zoul \ +libs/timers/zoul \ +libs/energest/zoul \ +libs/trickle-library/zoul \ +libs/data-structures/zoul \ +nullnet/zoul \ +slip-radio/zoul \ +dev/gpio-hal/zoul:BOARD=remote-reva \ +dev/gpio-hal/zoul:BOARD=remote-revb \ +dev/gpio-hal/zoul:BOARD=firefly-reva \ +dev/gpio-hal/zoul:BOARD=firefly \ +dev/gpio-hal/zoul:BOARD=orion \ +dev/leds/zoul:BOARD=remote-reva \ +dev/leds/zoul:BOARD=remote-revb \ +dev/leds/zoul:BOARD=firefly-reva \ +dev/leds/zoul:BOARD=firefly \ +dev/leds/zoul:BOARD=orion \ +dev/rgb-led/zoul:BOARD=remote-reva \ +dev/rgb-led/zoul:BOARD=remote-revb \ +dev/rgb-led/zoul:BOARD=firefly-reva \ +dev/rgb-led/zoul:BOARD=firefly \ +dev/rgb-led/zoul:BOARD=orion \ +mqtt-client/zoul:BOARD=firefly \ +mqtt-client/openmote-cc2538 \ +storage/cfs-coffee/openmote-cc2538 \ +sensniff/openmote-cc2538 \ +hello-world/openmote-cc2538 \ +rpl-udp/openmote-cc2538 \ +dev/gpio-hal/openmote-cc2538 \ +dev/leds/openmote-cc2538 \ +rpl-border-router/openmote-cc2538 \ +libs/ipv6-hooks/openmote-cc2538 \ + +TOOLS= + +include ../Makefile.compile-test diff --git a/tests/04-compile-nrf52-ports/Makefile b/tests/04-compile-nrf52-ports/Makefile deleted file mode 100644 index 7f4ad4f2dd8e8ff007eeb8c1a26437eb6660a5d5..0000000000000000000000000000000000000000 --- a/tests/04-compile-nrf52-ports/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -EXAMPLESDIR=../../examples -TOOLSDIR=../../tools - -# Note, that SERVER_IPV6_ADDR variable is set to ffff on purpose -# even though it's not a valid IPV6 address. This is due to limitation -# of the testing framework which splits compliation arguments using -# a colon. - -EXAMPLES = \ -hello-world/nrf52dk \ -platform-specific/nrf52dk/coap-demo/nrf52dk:coap-server \ -platform-specific/nrf52dk/coap-demo/nrf52dk:coap-client:SERVER_IPV6_ADDR=ffff \ -platform-specific/nrf52dk/mqtt-demo/nrf52dk \ -platform-specific/nrf52dk/blink-hello/nrf52dk \ -platform-specific/nrf52dk/timer-test/nrf52dk \ -libs/logging/nrf52dk - -TOOLS= - -include ../Makefile.compile-test diff --git a/tests/03-compile-nxp-ports/Makefile b/tests/04-compile-nxp-ports/Makefile similarity index 91% rename from tests/03-compile-nxp-ports/Makefile rename to tests/04-compile-nxp-ports/Makefile index b1fdd9ea698cdc4ccd52d0a7005b6256165112c9..214bced26a640a7bde7ffc5eb91deecb30b30de9 100644 --- a/tests/03-compile-nxp-ports/Makefile +++ b/tests/04-compile-nxp-ports/Makefile @@ -11,8 +11,9 @@ platform-specific/jn516x/rpl/coap-dr1175-node/jn516x \ platform-specific/jn516x/rpl/coap-dr1199-node/jn516x \ platform-specific/jn516x/tsch/simple-sensor-network/node/jn516x \ platform-specific/jn516x/tsch/tx-power-verification/node/jn516x \ -platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/jn516x \ platform-specific/jn516x/tsch/uart1-test-node/jn516x \ +coap/coap-example-client/jn516x \ +coap/coap-example-server/jn516x \ sensniff/jn516x \ rpl-border-router/jn516x \ 6tisch/simple-node/jn516x \ diff --git a/tests/05-compile-tools/Makefile b/tests/05-compile-tools/Makefile index 7d571f7728762975f622b7761199926b75f65a00..43f84405ad26b11afecb51311560e19daf9f2e09 100644 --- a/tests/05-compile-tools/Makefile +++ b/tests/05-compile-tools/Makefile @@ -25,47 +25,24 @@ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. -TOOLS=sky tools -FAILTOOLS=sky=uip6-bridge +TOOLS=tools tools/sky tools/jn516x +BASEDIR=../../ +TESTLOGS=$(subst /,__,$(patsubst %,%.testlog, $(TOOLS))) +all: clean summary -TOOLSDIR=../../tools -LOGS=$(patsubst %,%.log, $(TOOLS)) +%.testlog: + @echo -n Building tool: $(basename $@) + @printf "%-32s" "$@" > $@ + @$(MAKE) -C $(BASEDIR)/$(basename $(subst __,/,$@)) clean > /dev/null && \ + $(MAKE) -C $(BASEDIR)/$(basename $(subst __,/,$@)) > /dev/null && \ + (echo " -> OK" && echo "TEST OK" >> $@) || \ + (echo " -> FAIL" && echo "TEST FAIL" >> $@) -all: summary - -FRC: - - -sky.log: RMFILES=serialdump-linux - - -tools.log: - @$(MAKE) -C $(TOOLSDIR) > $@ 2>&1 && $(RM) $@.failed || touch $@.failed - - -%.log: FRC - @( cd $(TOOLSDIR)/$(subst =,/,$*) && $(RM) $(RMFILES) ) - @touch $@ - @$(MAKE) -C $(TOOLSDIR)/$(subst =,/,$*) > $@ 2>&1 && $(RM) $@.failed || touch $@.failed - - -summary: $(LOGS) - @(\ - for T in $(TOOLS) ; do \ - if [ -f $$T.log.failed ] ; then \ - echo tools/$$T: FAIL ಠ_ಠ >> $@;\ - cat $$T.log >> $@;\ - else \ - echo tools/$$T: OK >> $@;\ - fi\ - done \ - ) - @echo "Info: The following tools need fixing and are not tested:" $(subst =,/,$(FAILTOOLS)) >> $@ - @echo $@ +summary: $(TESTLOGS) + @cat *.testlog > summary + @echo "========== Summary ==========" + @cat summary clean: - @make -C $(DOCDIR) clean - - -.PHONY: %.log + @rm -f *.testlog summary diff --git a/tests/07-base/02-hello-world-sky.csc b/tests/07-simulation-base/01-hello-world-sky.csc similarity index 95% rename from tests/07-base/02-hello-world-sky.csc rename to tests/07-simulation-base/01-hello-world-sky.csc index 1c656fc71d4b677acd1f10c557cb2fa8ec1b53b7..050631b7034cb7560a8ad392acbe0cd61a364682 100644 --- a/tests/07-base/02-hello-world-sky.csc +++ b/tests/07-simulation-base/01-hello-world-sky.csc @@ -19,7 +19,7 @@ <identifier>sky1</identifier> <description>Sky Mote Type #1</description> <source EXPORT="discard">[CONTIKI_DIR]/examples/hello-world/hello-world.c</source> - <commands EXPORT="discard">make hello-world.sky TARGET=sky</commands> + <commands EXPORT="discard">make -j hello-world.sky TARGET=sky</commands> <firmware EXPORT="copy">[CONTIKI_DIR]/examples/hello-world/hello-world.sky</firmware> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface> @@ -50,7 +50,7 @@ <plugin> org.contikios.cooja.plugins.ScriptRunner <plugin_config> - <scriptfile>[CONFIG_DIR]/hello-world.js</scriptfile> + <scriptfile>[CONFIG_DIR]/js/hello-world.js</scriptfile> <active>true</active> </plugin_config> <width>541</width> @@ -79,4 +79,3 @@ <location_y>288</location_y> </plugin> </simconf> - diff --git a/tests/07-base/04-ringbufindex.csc b/tests/07-simulation-base/02-ringbufindex.csc similarity index 98% rename from tests/07-base/04-ringbufindex.csc rename to tests/07-simulation-base/02-ringbufindex.csc index 4c70ff04c3c0caf319a0dbb9a674921fe2c030ec..5b236bc5afab06a95957a634837cdd4d386f9808 100644 --- a/tests/07-base/04-ringbufindex.csc +++ b/tests/07-simulation-base/02-ringbufindex.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <project EXPORT="discard">[APPS_DIR]/radiologger-headless</project> <simulation> @@ -25,7 +24,7 @@ org.contikios.cooja.contikimote.ContikiMoteType <identifier>mtype297</identifier> <description>ringbufindex testee</description> - <source>[CONFIG_DIR]/code/test-ringbufindex.c</source> + <source>[CONFIG_DIR]/code-ringbufindex/test-ringbufindex.c</source> <commands>make test-ringbufindex.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> diff --git a/tests/09-nullnet/01-nullnet-broadcast.csc b/tests/07-simulation-base/03-nullnet-broadcast.csc similarity index 99% rename from tests/09-nullnet/01-nullnet-broadcast.csc rename to tests/07-simulation-base/03-nullnet-broadcast.csc index 2715b13e239ef44cc030a35d5fbe3dee4591ce40..302a04b9b5ced316ea9738804f93eb667a4ee676 100644 --- a/tests/09-nullnet/01-nullnet-broadcast.csc +++ b/tests/07-simulation-base/03-nullnet-broadcast.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>NullNet Broadcast Example</title> @@ -26,7 +25,7 @@ <description>Cooja Mote Type #1</description> <source>[CONTIKI_DIR]/examples/nullnet/nullnet-broadcast.c</source> <commands>make TARGET=cooja clean -make nullnet-broadcast.cooja TARGET=cooja</commands> +make -j nullnet-broadcast.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> diff --git a/tests/09-nullnet/02-nullnet-broadcast-tsch.csc b/tests/07-simulation-base/04-nullnet-broadcast-tsch.csc similarity index 98% rename from tests/09-nullnet/02-nullnet-broadcast-tsch.csc rename to tests/07-simulation-base/04-nullnet-broadcast-tsch.csc index 3b3e0ee94118f3571375c640eb70b8a25888512b..498c7fcbebbfb3b01af3649c8c175c8c73e5d7f6 100644 --- a/tests/09-nullnet/02-nullnet-broadcast-tsch.csc +++ b/tests/07-simulation-base/04-nullnet-broadcast-tsch.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>NullNet Broadcast Example</title> @@ -26,7 +25,7 @@ <description>Cooja Mote Type #1</description> <source>[CONTIKI_DIR]/examples/nullnet/nullnet-broadcast.c</source> <commands>make TARGET=cooja clean -make nullnet-broadcast.cooja MAKE_MAC=MAKE_MAC_TSCH TARGET=cooja</commands> +make -j nullnet-broadcast.cooja MAKE_MAC=MAKE_MAC_TSCH TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> diff --git a/tests/09-nullnet/03-nullnet-unicast.csc b/tests/07-simulation-base/05-nullnet-unicast.csc similarity index 98% rename from tests/09-nullnet/03-nullnet-unicast.csc rename to tests/07-simulation-base/05-nullnet-unicast.csc index 2927eaee3153064bac6d3bb593d8652c95b944ec..12b6003173445557a7f3bfedb8915b856000f72e 100644 --- a/tests/09-nullnet/03-nullnet-unicast.csc +++ b/tests/07-simulation-base/05-nullnet-unicast.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>NullNet Broadcast Example</title> @@ -26,7 +25,7 @@ <description>Cooja Mote Type #1</description> <source>[CONTIKI_DIR]/examples/nullnet/nullnet-broadcast.c</source> <commands>make TARGET=cooja clean -make nullnet-broadcast.cooja TARGET=cooja</commands> +make -j nullnet-broadcast.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> diff --git a/tests/09-nullnet/04-nullnet-unicast-tsch.csc b/tests/07-simulation-base/06-nullnet-unicast-tsch.csc similarity index 98% rename from tests/09-nullnet/04-nullnet-unicast-tsch.csc rename to tests/07-simulation-base/06-nullnet-unicast-tsch.csc index cad3430cf8c06294d0a6a512d164e226bbe2ada1..e6424709574d75be155ccf2bf6593d9cc10cfc3c 100644 --- a/tests/09-nullnet/04-nullnet-unicast-tsch.csc +++ b/tests/07-simulation-base/06-nullnet-unicast-tsch.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>NullNet Broadcast Example</title> @@ -26,7 +25,7 @@ <description>Cooja Mote Type #1</description> <source>[CONTIKI_DIR]/examples/nullnet/nullnet-broadcast.c</source> <commands>make TARGET=cooja clean -make nullnet-broadcast.cooja MAKE_MAC=MAKE_MAC_TSCH TARGET=cooja</commands> +make -j nullnet-broadcast.cooja MAKE_MAC=MAKE_MAC_TSCH TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> diff --git a/tests/08-ipv6/15-cooja-multicast-11-hops-rollt-tm.csc b/tests/07-simulation-base/15-cooja-multicast-11-hops-rollt-tm.csc similarity index 97% rename from tests/08-ipv6/15-cooja-multicast-11-hops-rollt-tm.csc rename to tests/07-simulation-base/15-cooja-multicast-11-hops-rollt-tm.csc index 8fdc9fcd94bdc1c5bda3bc471dcc64c392379769..473df16dd17e1eb2fb49ea9a0e0c729d98161dc8 100644 --- a/tests/08-ipv6/15-cooja-multicast-11-hops-rollt-tm.csc +++ b/tests/07-simulation-base/15-cooja-multicast-11-hops-rollt-tm.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>Multicast regression test</title> @@ -25,7 +24,7 @@ <identifier>mtype612</identifier> <description>Root/sender</description> <source>[CONTIKI_DIR]/examples/multicast/root.c</source> - <commands>make root.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_ROLL_TM</commands> + <commands>make -j root.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_ROLL_TM</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -49,7 +48,7 @@ <identifier>mtype890</identifier> <description>Intermediate</description> <source>[CONTIKI_DIR]/examples/multicast/intermediate.c</source> - <commands>make intermediate.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_ROLL_TM</commands> + <commands>make -j intermediate.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_ROLL_TM</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -364,4 +363,3 @@ log.testOK(); /* Report test success and quit */</script> <location_y>77</location_y> </plugin> </simconf> - diff --git a/tests/08-ipv6/16-cooja-multicast-11-hops-smrf.csc b/tests/07-simulation-base/16-cooja-multicast-11-hops-smrf.csc similarity index 97% rename from tests/08-ipv6/16-cooja-multicast-11-hops-smrf.csc rename to tests/07-simulation-base/16-cooja-multicast-11-hops-smrf.csc index c995410324d6a1b7cc67f83b499b71aec22abaa5..e20a30cb6860ff43c4c44276adb6489a39c655c4 100644 --- a/tests/08-ipv6/16-cooja-multicast-11-hops-smrf.csc +++ b/tests/07-simulation-base/16-cooja-multicast-11-hops-smrf.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>Multicast regression test</title> @@ -25,7 +24,7 @@ <identifier>mtype612</identifier> <description>Root/sender</description> <source>[CONTIKI_DIR]/examples/multicast/root.c</source> - <commands>make root.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_SMRF</commands> + <commands>make -j root.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_SMRF</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -49,7 +48,7 @@ <identifier>mtype890</identifier> <description>Intermediate</description> <source>[CONTIKI_DIR]/examples/multicast/intermediate.c</source> - <commands>make intermediate.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_SMRF</commands> + <commands>make -j intermediate.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_SMRF</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -73,7 +72,7 @@ <identifier>mtype956</identifier> <description>Receiver</description> <source>[CONTIKI_DIR]/examples/multicast/sink.c</source> - <commands>make sink.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_SMRF</commands> + <commands>make -j sink.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_SMRF</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -364,4 +363,3 @@ log.testOK(); /* Report test success and quit */</script> <location_y>77</location_y> </plugin> </simconf> - diff --git a/tests/08-ipv6/17-cooja-multicast-11-hops-esmrf.csc b/tests/07-simulation-base/17-cooja-multicast-11-hops-esmrf.csc similarity index 97% rename from tests/08-ipv6/17-cooja-multicast-11-hops-esmrf.csc rename to tests/07-simulation-base/17-cooja-multicast-11-hops-esmrf.csc index 6c68043d15d36086f2b0eaef6e943853746ee452..14b74b41ed08c090800a218d94aa7fd7063e7a82 100644 --- a/tests/08-ipv6/17-cooja-multicast-11-hops-esmrf.csc +++ b/tests/07-simulation-base/17-cooja-multicast-11-hops-esmrf.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>Multicast regression test</title> @@ -25,7 +24,7 @@ <identifier>mtype612</identifier> <description>Root/sender</description> <source>[CONTIKI_DIR]/examples/multicast/root.c</source> - <commands>make root.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_ESMRF</commands> + <commands>make -j root.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_ESMRF</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -49,7 +48,7 @@ <identifier>mtype890</identifier> <description>Intermediate</description> <source>[CONTIKI_DIR]/examples/multicast/intermediate.c</source> - <commands>make intermediate.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_ESMRF</commands> + <commands>make -j intermediate.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_ESMRF</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -364,4 +363,3 @@ log.testOK(); /* Report test success and quit */</script> <location_y>77</location_y> </plugin> </simconf> - diff --git a/tests/08-ipv6/18-cooja-multicast-31-hops.csc b/tests/07-simulation-base/18-cooja-multicast-31-hops.csc similarity index 99% rename from tests/08-ipv6/18-cooja-multicast-31-hops.csc rename to tests/07-simulation-base/18-cooja-multicast-31-hops.csc index 1da00d7cf42e752ef151a661360542e46b3eb1cb..86ae6916f2e151ea1d8615fdb54498c11d7913e4 100644 --- a/tests/08-ipv6/18-cooja-multicast-31-hops.csc +++ b/tests/07-simulation-base/18-cooja-multicast-31-hops.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>Multicast regression test</title> @@ -25,7 +24,7 @@ <identifier>mtype816</identifier> <description>Root/sender</description> <source>[CONTIKI_DIR]/examples/multicast/root.c</source> - <commands>make root.cooja TARGET=cooja</commands> + <commands>make -j root.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -49,7 +48,7 @@ <identifier>mtype53</identifier> <description>Intermediate</description> <source>[CONTIKI_DIR]/examples/multicast/intermediate.c</source> - <commands>make intermediate.cooja TARGET=cooja</commands> + <commands>make -j intermediate.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -73,7 +72,7 @@ <identifier>mtype191</identifier> <description>Receiver</description> <source>[CONTIKI_DIR]/examples/multicast/sink.c</source> - <commands>make sink.cooja TARGET=cooja</commands> + <commands>make -j sink.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -704,4 +703,3 @@ log.testOK(); /* Report test success and quit */</script> <location_y>77</location_y> </plugin> </simconf> - diff --git a/tests/08-ipv6/19-cooja-rpl-tsch.csc b/tests/07-simulation-base/19-cooja-rpl-tsch.csc similarity index 98% rename from tests/08-ipv6/19-cooja-rpl-tsch.csc rename to tests/07-simulation-base/19-cooja-rpl-tsch.csc index 694d9a0c164ee0437dd5e8161a444438d0f9abff..99e11d63db02a9064b795451502ad1b7bb9df4fa 100644 --- a/tests/08-ipv6/19-cooja-rpl-tsch.csc +++ b/tests/07-simulation-base/19-cooja-rpl-tsch.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>RPL+TSCH</title> @@ -26,7 +25,7 @@ <description>Cooja Mote Type #mtype1</description> <source EXPORT="discard">[CONTIKI_DIR]/examples/6tisch/simple-node/node.c</source> <commands EXPORT="discard">make TARGET=cooja clean -make node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=0 MAKE_WITH_SECURITY=0 MAKE_WITH_PERIODIC_ROUTES_PRINT=1</commands> +make -j node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=0 MAKE_WITH_SECURITY=0 MAKE_WITH_PERIODIC_ROUTES_PRINT=1</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> diff --git a/tests/08-ipv6/20-cooja-rpl-tsch-orchestra.csc b/tests/07-simulation-base/20-cooja-rpl-tsch-orchestra.csc similarity index 98% rename from tests/08-ipv6/20-cooja-rpl-tsch-orchestra.csc rename to tests/07-simulation-base/20-cooja-rpl-tsch-orchestra.csc index 7593ae9b222265ba4031be2a9c9b1b536bb99f08..5ce2c81215ba3f6efcb186c3407a6344e5ee3645 100644 --- a/tests/08-ipv6/20-cooja-rpl-tsch-orchestra.csc +++ b/tests/07-simulation-base/20-cooja-rpl-tsch-orchestra.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>RPL+TSCH+Orchestrsa</title> @@ -26,7 +25,7 @@ <description>Cooja Mote Type #mtype11</description> <source EXPORT="discard">[CONTIKI_DIR]/examples/6tisch/simple-node/node.c</source> <commands EXPORT="discard">make TARGET=cooja clean -make node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=1 MAKE_WITH_SECURITY=0 MAKE_WITH_PERIODIC_ROUTES_PRINT=1</commands> +make -j node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=1 MAKE_WITH_SECURITY=0 MAKE_WITH_PERIODIC_ROUTES_PRINT=1</commands> <firmware EXPORT="copy">[CONTIKI_DIR]/examples/6tisch/simple-node/node.mtype1</firmware> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> @@ -294,4 +293,3 @@ while(true) {;
 <location_y>111</location_y> </plugin> </simconf> - diff --git a/tests/08-ipv6/21-cooja-rpl-tsch-security.csc b/tests/07-simulation-base/21-cooja-rpl-tsch-security.csc similarity index 98% rename from tests/08-ipv6/21-cooja-rpl-tsch-security.csc rename to tests/07-simulation-base/21-cooja-rpl-tsch-security.csc index 5da4a0f32fe62b8004630395f49feb0f51ff6948..c34e6c4cf2be37622f81010116bf913e08e3f92f 100644 --- a/tests/08-ipv6/21-cooja-rpl-tsch-security.csc +++ b/tests/07-simulation-base/21-cooja-rpl-tsch-security.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>RPL+TSCH+Security</title> @@ -26,7 +25,7 @@ <description>Cooja Mote Type #mtype11</description> <source EXPORT="discard">[CONTIKI_DIR]/examples/6tisch/simple-node/node.c</source> <commands EXPORT="discard">make TARGET=cooja clean -make node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=0 MAKE_WITH_SECURITY=1 MAKE_WITH_PERIODIC_ROUTES_PRINT=1</commands> +make -j node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=0 MAKE_WITH_SECURITY=1 MAKE_WITH_PERIODIC_ROUTES_PRINT=1</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -292,4 +291,3 @@ while(true) {;
 <location_y>111</location_y> </plugin> </simconf> - diff --git a/tests/07-simulation-base/22-stack-guard-sky.csc b/tests/07-simulation-base/22-stack-guard-sky.csc new file mode 100644 index 0000000000000000000000000000000000000000..5d57eb148d0402a0151e17017e02b89eeb4221c6 --- /dev/null +++ b/tests/07-simulation-base/22-stack-guard-sky.csc @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<simconf> + <simulation> + <title>Stack guard test (Sky)</title> + <randomseed>123456</randomseed> + <motedelay_us>1000000</motedelay_us> + <radiomedium> + org.contikios.cooja.radiomediums.UDGM + <transmitting_range>50.0</transmitting_range> + <interference_range>100.0</interference_range> + <success_ratio_tx>1.0</success_ratio_tx> + <success_ratio_rx>1.0</success_ratio_rx> + </radiomedium> + <events> + <logoutput>40000</logoutput> + </events> + <motetype> + org.contikios.cooja.mspmote.SkyMoteType + <identifier>sky1</identifier> + <description>Sky Mote Type #1</description> + <source EXPORT="discard">[CONTIKI_DIR]/examples/libs/stack-check/example-stack-check.c</source> + <commands EXPORT="discard">make -j example-stack-check.sky TARGET=sky</commands> + <firmware EXPORT="copy">[CONTIKI_DIR]/examples/libs/stack-check/example-stack-check.sky</firmware> + <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface> + </motetype> + <mote> + <breakpoints /> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>64.11203103628397</x> + <y>93.06735634828134</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.mspmote.interfaces.MspMoteID + <id>1</id> + </interface_config> + <motetype_identifier>sky1</motetype_identifier> + </mote> + </simulation> + <plugin> + org.contikios.cooja.plugins.ScriptRunner + <plugin_config> + <scriptfile>[CONFIG_DIR]/js/22-stack-check.js</scriptfile> + <active>true</active> + </plugin_config> + <width>541</width> + <z>0</z> + <height>448</height> + <location_x>299</location_x> + <location_y>7</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.SimControl + <width>280</width> + <z>2</z> + <height>160</height> + <location_x>7</location_x> + <location_y>10</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.LogListener + <plugin_config> + <filter /> + </plugin_config> + <width>680</width> + <z>1</z> + <height>240</height> + <location_x>51</location_x> + <location_y>288</location_y> + </plugin> +</simconf> diff --git a/tests/07-simulation-base/31-data-structures-sky.csc b/tests/07-simulation-base/31-data-structures-sky.csc new file mode 100644 index 0000000000000000000000000000000000000000..0e4e81069dede12169bccac606cfa43fb91eb70f --- /dev/null +++ b/tests/07-simulation-base/31-data-structures-sky.csc @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="UTF-8"?> +<simconf> + <project EXPORT="discard">[APPS_DIR]/mrm</project> + <project EXPORT="discard">[APPS_DIR]/mspsim</project> + <project EXPORT="discard">[APPS_DIR]/avrora</project> + <project EXPORT="discard">[APPS_DIR]/serial_socket</project> + <project EXPORT="discard">[APPS_DIR]/powertracker</project> + <simulation> + <title>data-structures-sky</title> + <randomseed>123456</randomseed> + <motedelay_us>1000000</motedelay_us> + <radiomedium> + org.contikios.cooja.radiomediums.UDGM + <transmitting_range>50.0</transmitting_range> + <interference_range>100.0</interference_range> + <success_ratio_tx>1.0</success_ratio_tx> + <success_ratio_rx>1.0</success_ratio_rx> + </radiomedium> + <events> + <logoutput>40000</logoutput> + </events> + <motetype> + org.contikios.cooja.mspmote.SkyMoteType + <identifier>sky1</identifier> + <description>Sky Mote Type #sky1</description> + <source EXPORT="discard">[CONTIKI_DIR]/tests/07-simulation-base/code-data-structures/test-data-structures.c</source> + <commands EXPORT="discard">make test-data-structures.sky TARGET=sky</commands> + <firmware EXPORT="copy">[CONTIKI_DIR]/tests/07-simulation-base/code-data-structures/test-data-structures.sky</firmware> + <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface> + <moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface> + </motetype> + <mote> + <breakpoints /> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>3.086692968239446</x> + <y>5.726233183606267</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.mspmote.interfaces.MspClock + <deviation>1.0</deviation> + </interface_config> + <interface_config> + org.contikios.cooja.mspmote.interfaces.MspMoteID + <id>1</id> + </interface_config> + <motetype_identifier>sky1</motetype_identifier> + </mote> + </simulation> + <plugin> + org.contikios.cooja.plugins.SimControl + <width>280</width> + <z>2</z> + <height>160</height> + <location_x>400</location_x> + <location_y>0</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.LogListener + <plugin_config> + <filter /> + <formatted_time /> + <coloring /> + </plugin_config> + <width>586</width> + <z>1</z> + <height>666</height> + <location_x>400</location_x> + <location_y>160</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.ScriptRunner + <plugin_config> + <scriptfile>[CONFIG_DIR]/js/data-structures.js</scriptfile> + <active>true</active> + </plugin_config> + <width>600</width> + <z>0</z> + <height>700</height> + <location_x>5</location_x> + <location_y>1</location_y> + </plugin> +</simconf> diff --git a/tests/07-base/Makefile b/tests/07-simulation-base/Makefile similarity index 100% rename from tests/07-base/Makefile rename to tests/07-simulation-base/Makefile diff --git a/tests/07-simulation-base/code-data-structures/Makefile b/tests/07-simulation-base/code-data-structures/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d88177bbead2af8c8399d2cae5f41df78acb5bb7 --- /dev/null +++ b/tests/07-simulation-base/code-data-structures/Makefile @@ -0,0 +1,9 @@ +all: test-data-structures + +MODULES += os/services/unit-test + +MAKE_MAC = MAKE_MAC_NULLMAC +MAKE_NET = MAKE_NET_NULLNET + +CONTIKI = ../../.. +include $(CONTIKI)/Makefile.include diff --git a/arch/cpu/cc2538/debug-uart.h b/tests/07-simulation-base/code-data-structures/project-conf.h similarity index 79% rename from arch/cpu/cc2538/debug-uart.h rename to tests/07-simulation-base/code-data-structures/project-conf.h index 88a2fc3e0be520fc3f9cd54e1b06a0d757cb88ab..1e6d488093a85dc3461c8df9df825792b8abe173 100644 --- a/arch/cpu/cc2538/debug-uart.h +++ b/tests/07-simulation-base/code-data-structures/project-conf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2017, Yasuyuki Tanaka * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,20 +28,10 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * \addtogroup cc2538-char-io - * @{ - * - * \file - * This file is here because DBG I/O expects it to be. It just includes - * our own dbg.h which has a non-misleading name and which also adheres - * to Contiki's naming convention - */ -#ifndef DEBUG_UART_H_ -#define DEBUG_UART_H_ -#include "dbg.h" +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ -#endif /* DEBUG_UART_H_ */ +#define UNIT_TEST_PRINT_FUNCTION print_test_report -/** @} */ +#endif /* PROJECT_CONF_H_ */ diff --git a/tests/07-simulation-base/code-data-structures/test-data-structures.c b/tests/07-simulation-base/code-data-structures/test-data-structures.c new file mode 100644 index 0000000000000000000000000000000000000000..dc4d8bb5bf4f658fbc938e7cbdcf9f5a49bdca84 --- /dev/null +++ b/tests/07-simulation-base/code-data-structures/test-data-structures.c @@ -0,0 +1,1034 @@ +/* + * Copyright (c) 2017, George Oikonomou - http://www.spd.gr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/list.h" +#include "lib/stack.h" +#include "lib/queue.h" +#include "lib/circular-list.h" +#include "lib/dbl-list.h" +#include "lib/dbl-circ-list.h" +#include "lib/random.h" +#include "services/unit-test/unit-test.h" + +#include <string.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +/*---------------------------------------------------------------------------*/ +PROCESS(data_structure_test_process, "Data structure process"); +AUTOSTART_PROCESSES(&data_structure_test_process); +/*---------------------------------------------------------------------------*/ +typedef struct demo_struct_s { + struct demo_struct_s *next; + struct demo_struct_s *previous; +} demo_struct_t; +/*---------------------------------------------------------------------------*/ +#define ELEMENT_COUNT 10 +static demo_struct_t elements[ELEMENT_COUNT]; +/*---------------------------------------------------------------------------*/ +void +print_test_report(const unit_test_t *utp) +{ + printf("=check-me= "); + if(utp->result == unit_test_failure) { + printf("FAILED - %s: exit at L%u\n", utp->descr, utp->exit_line); + } else { + printf("SUCCEEDED - %s\n", utp->descr); + } +} +/*---------------------------------------------------------------------------*/ +UNIT_TEST_REGISTER(test_list, "Singly-linked list"); +UNIT_TEST(test_list) +{ + demo_struct_t *head, *tail; + + LIST(lst); + + UNIT_TEST_BEGIN(); + + memset(elements, 0, sizeof(elements)); + list_init(lst); + + /* Starts from empty */ + UNIT_TEST_ASSERT(list_head(lst) == NULL); + UNIT_TEST_ASSERT(list_length(lst) == 0); + + /* + * Add an item. Should be head and tail + * 0 --> NULL + */ + list_add(lst, &elements[0]); + UNIT_TEST_ASSERT(list_head(lst) == &elements[0]); + UNIT_TEST_ASSERT(list_tail(lst) == &elements[0]); + UNIT_TEST_ASSERT(elements[0].next == NULL); + UNIT_TEST_ASSERT(list_length(lst) == 1); + + /* + * Add an item. Should become the new tail + * 0 --> 1 --> NULL + */ + list_add(lst, &elements[1]); + head = list_head(lst); + tail = list_tail(lst); + UNIT_TEST_ASSERT(list_head(lst) == &elements[0]); + UNIT_TEST_ASSERT(list_tail(lst) == &elements[1]); + UNIT_TEST_ASSERT(head->next == tail); + UNIT_TEST_ASSERT(tail->next == NULL); + UNIT_TEST_ASSERT(list_length(lst) == 2); + + /* + * Add after existing head + * 0 --> 2 --> 1 --> NULL + */ + head = list_head(lst); + list_insert(lst, head, &elements[2]); + head = list_head(lst); + tail = list_tail(lst); + UNIT_TEST_ASSERT(list_head(lst) == &elements[0]); + UNIT_TEST_ASSERT(list_tail(lst) == &elements[1]); + UNIT_TEST_ASSERT(head->next == &elements[2]); + UNIT_TEST_ASSERT(elements[2].next == tail); + UNIT_TEST_ASSERT(tail->next == NULL); + UNIT_TEST_ASSERT(list_length(lst) == 3); + + /* + * Add after existing head + * 0 --> 2 --> 1 --> 3 --> NULL + */ + tail = list_tail(lst); + list_insert(lst, tail, &elements[3]); + tail = list_tail(lst); + UNIT_TEST_ASSERT(list_head(lst) == &elements[0]); + UNIT_TEST_ASSERT(list_tail(lst) == &elements[3]); + UNIT_TEST_ASSERT(tail->next == NULL); + UNIT_TEST_ASSERT(list_length(lst) == 4); + + /* + * Re-add item 2 using list_add + * 0 --> 1 --> 3 --> 2 --> NULL + */ + list_add(lst, &elements[2]); + tail = list_tail(lst); + UNIT_TEST_ASSERT(list_head(lst) == &elements[0]); + UNIT_TEST_ASSERT(list_tail(lst) == &elements[2]); + UNIT_TEST_ASSERT(tail->next == NULL); + UNIT_TEST_ASSERT(list_length(lst) == 4); + + /* + * Re-add item 3 using list_insert + * 0 --> 1 --> 2 --> 3 --> NULL + */ + tail = list_tail(lst); + list_insert(lst, tail, &elements[3]); + tail = list_tail(lst); + UNIT_TEST_ASSERT(list_head(lst) == &elements[0]); + UNIT_TEST_ASSERT(list_tail(lst) == &elements[3]); + UNIT_TEST_ASSERT(elements[2].next == tail); + UNIT_TEST_ASSERT(tail->next == NULL); + UNIT_TEST_ASSERT(list_length(lst) == 4); + + /* + * Remove the tail + * 0 --> 1 --> 2 --> NULL + */ + tail = list_tail(lst); + UNIT_TEST_ASSERT(list_chop(lst) == tail); + head = list_head(lst); + tail = list_tail(lst); + UNIT_TEST_ASSERT(tail == &elements[2]); + UNIT_TEST_ASSERT(tail->next == NULL); + UNIT_TEST_ASSERT(list_length(lst) == 3); + + /* + * Remove an item in the middle + * 0 --> 2 --> NULL + */ + head = list_head(lst); + list_remove(lst, head->next); + head = list_head(lst); + tail = list_tail(lst); + UNIT_TEST_ASSERT(head->next == tail); + UNIT_TEST_ASSERT(list_head(lst) == &elements[0]); + UNIT_TEST_ASSERT(list_tail(lst) == &elements[2]); + UNIT_TEST_ASSERT(tail->next == NULL); + UNIT_TEST_ASSERT(list_length(lst) == 2); + + /* + * Remove the head + * 2 --> NULL + */ + list_remove(lst, list_head(lst)); + tail = list_tail(lst); + UNIT_TEST_ASSERT(list_head(lst) == &elements[2]); + UNIT_TEST_ASSERT(list_tail(lst) == &elements[2]); + UNIT_TEST_ASSERT(tail->next == NULL); + UNIT_TEST_ASSERT(list_length(lst) == 1); + + /* Ends empty */ + list_remove(lst, list_tail(lst)); + UNIT_TEST_ASSERT(list_head(lst) == NULL); + UNIT_TEST_ASSERT(list_length(lst) == 0); + + UNIT_TEST_END(); +} +/*---------------------------------------------------------------------------*/ +UNIT_TEST_REGISTER(test_stack, "Stack Push/Pop"); +UNIT_TEST(test_stack) +{ + STACK(stack); + + UNIT_TEST_BEGIN(); + + memset(elements, 0, sizeof(elements)); + stack_init(stack); + + /* Starts from empty */ + UNIT_TEST_ASSERT(stack_is_empty(stack) == true); + UNIT_TEST_ASSERT(stack_peek(stack) == NULL); + UNIT_TEST_ASSERT(stack_pop(stack) == NULL); + + /* + * Push two elements. Peek and pop should be the last one. Stack should be + * non-empty after the pop + */ + stack_push(stack, &elements[0]); + stack_push(stack, &elements[1]); + + UNIT_TEST_ASSERT(stack_peek(stack) == &elements[1]); + UNIT_TEST_ASSERT(stack_pop(stack) == &elements[1]); + UNIT_TEST_ASSERT(stack_peek(stack) == &elements[0]); + UNIT_TEST_ASSERT(stack_is_empty(stack) == false); + UNIT_TEST_ASSERT(stack_pop(stack) == &elements[0]); + + /* Ends empty */ + UNIT_TEST_ASSERT(stack_is_empty(stack) == true); + UNIT_TEST_ASSERT(stack_peek(stack) == NULL); + UNIT_TEST_ASSERT(stack_pop(stack) == NULL); + + UNIT_TEST_END(); +} +/*---------------------------------------------------------------------------*/ +UNIT_TEST_REGISTER(test_queue, "Queue Enqueue/Dequeue"); +UNIT_TEST(test_queue) +{ + QUEUE(queue); + + UNIT_TEST_BEGIN(); + + memset(elements, 0, sizeof(elements)); + queue_init(queue); + + /* Starts from empty */ + UNIT_TEST_ASSERT(queue_is_empty(queue) == true); + UNIT_TEST_ASSERT(queue_peek(queue) == NULL); + UNIT_TEST_ASSERT(queue_dequeue(queue) == NULL); + + /* Enqueue three elements. They should come out in the same order */ + queue_enqueue(queue, &elements[0]); + queue_enqueue(queue, &elements[1]); + queue_enqueue(queue, &elements[2]); + + UNIT_TEST_ASSERT(queue_dequeue(queue) == &elements[0]); + UNIT_TEST_ASSERT(queue_dequeue(queue) == &elements[1]); + UNIT_TEST_ASSERT(queue_dequeue(queue) == &elements[2]); + + /* Should be empty */ + UNIT_TEST_ASSERT(queue_is_empty(queue) == true); + UNIT_TEST_ASSERT(queue_peek(queue) == NULL); + UNIT_TEST_ASSERT(queue_dequeue(queue) == NULL); + + UNIT_TEST_END(); +} +/*---------------------------------------------------------------------------*/ +UNIT_TEST_REGISTER(test_csll, "Circular, singly-linked list"); +UNIT_TEST(test_csll) +{ + demo_struct_t *head, *tail; + + CIRCULAR_LIST(csll); + + UNIT_TEST_BEGIN(); + + memset(elements, 0, sizeof(elements)); + circular_list_init(csll); + + /* Starts from empty */ + UNIT_TEST_ASSERT(circular_list_is_empty(csll) == true); + UNIT_TEST_ASSERT(circular_list_length(csll) == 0); + UNIT_TEST_ASSERT(circular_list_head(csll) == NULL); + UNIT_TEST_ASSERT(circular_list_tail(csll) == NULL); + + /* Add one element. Should point to itself and act as head and tail */ + circular_list_add(csll, &elements[0]); + + UNIT_TEST_ASSERT(circular_list_is_empty(csll) == false); + UNIT_TEST_ASSERT(circular_list_length(csll) == 1); + UNIT_TEST_ASSERT(circular_list_head(csll) == &elements[0]); + UNIT_TEST_ASSERT(circular_list_tail(csll) == &elements[0]); + UNIT_TEST_ASSERT(elements[0].next == &elements[0]); + + /* Add a second element. The two should point to each-other */ + circular_list_add(csll, &elements[1]); + UNIT_TEST_ASSERT(elements[0].next == &elements[1]); + UNIT_TEST_ASSERT(elements[1].next == &elements[0]); + + /* + * Add a third element and check that head->next->next points to tail. + * Check that tail->next points to the head + */ + circular_list_add(csll, &elements[2]); + head = circular_list_head(csll); + tail = circular_list_tail(csll); + + UNIT_TEST_ASSERT(head->next->next == circular_list_tail(csll)); + UNIT_TEST_ASSERT(tail->next == circular_list_head(csll)); + + /* Re-add an existing element. Check the list's integrity */ + circular_list_add(csll, &elements[1]); + head = circular_list_head(csll); + tail = circular_list_tail(csll); + + UNIT_TEST_ASSERT(circular_list_is_empty(csll) == false); + UNIT_TEST_ASSERT(circular_list_length(csll) == 3); + UNIT_TEST_ASSERT(head->next->next->next == circular_list_head(csll)); + UNIT_TEST_ASSERT(head->next->next == circular_list_tail(csll)); + UNIT_TEST_ASSERT(tail->next == circular_list_head(csll)); + + /* Add another two elements, then start testing removal */ + circular_list_add(csll, &elements[3]); + circular_list_add(csll, &elements[4]); + + /* Remove an item in the middle and test list integrity */ + head = circular_list_head(csll); + circular_list_remove(csll, head->next->next); + head = circular_list_head(csll); + tail = circular_list_tail(csll); + + UNIT_TEST_ASSERT(circular_list_length(csll) == 4); + UNIT_TEST_ASSERT(head->next->next->next->next == circular_list_head(csll)); + UNIT_TEST_ASSERT(head->next->next->next == circular_list_tail(csll)); + UNIT_TEST_ASSERT(tail->next == circular_list_head(csll)); + + /* Remove the head and test list integrity */ + circular_list_remove(csll, circular_list_head(csll)); + head = circular_list_head(csll); + tail = circular_list_tail(csll); + + UNIT_TEST_ASSERT(circular_list_length(csll) == 3); + UNIT_TEST_ASSERT(head->next->next->next == circular_list_head(csll)); + UNIT_TEST_ASSERT(head->next->next == circular_list_tail(csll)); + UNIT_TEST_ASSERT(tail->next == circular_list_head(csll)); + + /* Remove the tail and test list integrity */ + circular_list_remove(csll, circular_list_tail(csll)); + head = circular_list_head(csll); + tail = circular_list_tail(csll); + + UNIT_TEST_ASSERT(circular_list_length(csll) == 2); + UNIT_TEST_ASSERT(head->next->next == circular_list_head(csll)); + UNIT_TEST_ASSERT(head->next == circular_list_tail(csll)); + UNIT_TEST_ASSERT(tail->next == circular_list_head(csll)); + + /* + * Remove the tail + * Only one item left: Make sure the head and tail are the same and point to + * each other + */ + circular_list_remove(csll, circular_list_tail(csll)); + head = circular_list_head(csll); + tail = circular_list_tail(csll); + + UNIT_TEST_ASSERT(circular_list_length(csll) == 1); + UNIT_TEST_ASSERT(head == tail); + UNIT_TEST_ASSERT(head->next->next == circular_list_head(csll)); + UNIT_TEST_ASSERT(head->next == circular_list_head(csll)); + UNIT_TEST_ASSERT(head->next == circular_list_tail(csll)); + UNIT_TEST_ASSERT(tail->next == circular_list_head(csll)); + UNIT_TEST_ASSERT(tail->next == circular_list_tail(csll)); + + /* Remove the last element by removing the head */ + circular_list_remove(csll, circular_list_head(csll)); + UNIT_TEST_ASSERT(circular_list_is_empty(csll) == true); + UNIT_TEST_ASSERT(circular_list_length(csll) == 0); + UNIT_TEST_ASSERT(circular_list_head(csll) == NULL); + UNIT_TEST_ASSERT(circular_list_tail(csll) == NULL); + + /* Remove the last element by removing the tail */ + circular_list_add(csll, &elements[0]); + circular_list_remove(csll, circular_list_tail(csll)); + UNIT_TEST_ASSERT(circular_list_is_empty(csll) == true); + UNIT_TEST_ASSERT(circular_list_length(csll) == 0); + UNIT_TEST_ASSERT(circular_list_head(csll) == NULL); + UNIT_TEST_ASSERT(circular_list_tail(csll) == NULL); + + UNIT_TEST_END(); +} +/*---------------------------------------------------------------------------*/ +UNIT_TEST_REGISTER(test_dll, "Doubly-linked list"); +UNIT_TEST(test_dll) +{ + demo_struct_t *head, *tail; + + CIRCULAR_LIST(dll); + + UNIT_TEST_BEGIN(); + + memset(elements, 0, sizeof(elements)); + + /* Starts from empty */ + dbl_list_init(dll); + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == true); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 0); + UNIT_TEST_ASSERT(dbl_list_head(dll) == NULL); + UNIT_TEST_ASSERT(dbl_list_tail(dll) == NULL); + + /* + * Add an item by adding to the head. + * Head and tail should point to NULL in both directions + */ + dbl_list_add_head(dll, &elements[0]); + head = dbl_list_head(dll); + tail = dbl_list_tail(dll); + + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == false); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 1); + UNIT_TEST_ASSERT(head == &elements[0]); + UNIT_TEST_ASSERT(tail == &elements[0]); + UNIT_TEST_ASSERT(head->previous == NULL); + UNIT_TEST_ASSERT(head->next == NULL); + UNIT_TEST_ASSERT(tail->previous == NULL); + UNIT_TEST_ASSERT(tail->next == NULL); + + /* + * Add an item by adding to the tail. + * Head and tail should point to NULL in both directions + */ + dbl_list_remove(dll, dbl_list_head(dll)); + dbl_list_add_tail(dll, &elements[1]); + head = dbl_list_head(dll); + tail = dbl_list_tail(dll); + + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == false); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 1); + UNIT_TEST_ASSERT(head == &elements[1]); + UNIT_TEST_ASSERT(tail == &elements[1]); + UNIT_TEST_ASSERT(head->previous == NULL); + UNIT_TEST_ASSERT(head->next == NULL); + UNIT_TEST_ASSERT(tail->previous == NULL); + UNIT_TEST_ASSERT(tail->next == NULL); + + /* + * Add a second item to head. Head points forward to tail. + * Tail points backwards to head. + */ + dbl_list_add_head(dll, &elements[2]); + head = dbl_list_head(dll); + tail = dbl_list_tail(dll); + + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == false); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 2); + UNIT_TEST_ASSERT(head == &elements[2]); + UNIT_TEST_ASSERT(tail == &elements[1]); + UNIT_TEST_ASSERT(head->previous == NULL); + UNIT_TEST_ASSERT(head->next == tail); + UNIT_TEST_ASSERT(tail->previous == head); + UNIT_TEST_ASSERT(tail->next == NULL); + + /* + * Add before head. + * NULL <-- 3 --> 2 --> 1 --> NULL + */ + dbl_list_add_before(dll, dbl_list_head(dll), &elements[3]); + head = dbl_list_head(dll); + tail = dbl_list_tail(dll); + + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == false); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 3); + UNIT_TEST_ASSERT(head == &elements[3]); + UNIT_TEST_ASSERT(tail == &elements[1]); + UNIT_TEST_ASSERT(head->previous == NULL); + UNIT_TEST_ASSERT(head->next == &elements[2]); + UNIT_TEST_ASSERT(head->next->next == tail); + UNIT_TEST_ASSERT(head->next->next->next == NULL); + UNIT_TEST_ASSERT(tail->previous == &elements[2]); + UNIT_TEST_ASSERT(tail->previous->previous == &elements[3]); + UNIT_TEST_ASSERT(tail->previous->previous->previous == NULL); + UNIT_TEST_ASSERT(tail->next == NULL); + + /* + * Add after head. + * NULL <-- 3 --> 4 --> 2 --> 1 --> NULL + */ + dbl_list_add_after(dll, dbl_list_head(dll), &elements[4]); + head = dbl_list_head(dll); + tail = dbl_list_tail(dll); + + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == false); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 4); + UNIT_TEST_ASSERT(head == &elements[3]); + UNIT_TEST_ASSERT(tail == &elements[1]); + UNIT_TEST_ASSERT(head->previous == NULL); + UNIT_TEST_ASSERT(head->next == &elements[4]); + UNIT_TEST_ASSERT(head->next->next == &elements[2]); + UNIT_TEST_ASSERT(head->next->next->next == tail); + UNIT_TEST_ASSERT(head->next->next->next->next == NULL); + UNIT_TEST_ASSERT(tail->previous == &elements[2]); + UNIT_TEST_ASSERT(tail->previous->previous == &elements[4]); + UNIT_TEST_ASSERT(tail->previous->previous->previous == &elements[3]); + UNIT_TEST_ASSERT(tail->previous->previous->previous->previous == NULL); + UNIT_TEST_ASSERT(tail->next == NULL); + + /* + * Add at 3rd position by adding after 2nd + * NULL <-- 3 --> 4 --> 5 --> 2 --> 1 --> NULL + */ + dbl_list_add_after(dll, &elements[4], &elements[5]); + head = dbl_list_head(dll); + tail = dbl_list_tail(dll); + + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == false); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 5); + UNIT_TEST_ASSERT(head == &elements[3]); + UNIT_TEST_ASSERT(tail == &elements[1]); + UNIT_TEST_ASSERT(head->previous == NULL); + UNIT_TEST_ASSERT(head->next == &elements[4]); + UNIT_TEST_ASSERT(head->next->next == &elements[5]); + UNIT_TEST_ASSERT(tail->previous->previous == &elements[5]); + UNIT_TEST_ASSERT(tail->previous == &elements[2]); + UNIT_TEST_ASSERT(elements[5].next == &elements[2]); + UNIT_TEST_ASSERT(elements[5].previous == &elements[4]); + UNIT_TEST_ASSERT(tail->next == NULL); + + /* + * Add at 3rd position by adding before 3rd + * NULL <-- 3 --> 4 --> 6 --> 5 --> 2 --> 1 --> NULL + */ + dbl_list_add_before(dll, &elements[5], &elements[6]); + head = dbl_list_head(dll); + tail = dbl_list_tail(dll); + + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == false); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 6); + UNIT_TEST_ASSERT(head == &elements[3]); + UNIT_TEST_ASSERT(tail == &elements[1]); + UNIT_TEST_ASSERT(head->previous == NULL); + UNIT_TEST_ASSERT(head->next == &elements[4]); + UNIT_TEST_ASSERT(head->next->next == &elements[6]); + UNIT_TEST_ASSERT(tail->previous->previous == &elements[5]); + UNIT_TEST_ASSERT(elements[6].next == &elements[5]); + UNIT_TEST_ASSERT(elements[6].previous == &elements[4]); + UNIT_TEST_ASSERT(tail->next == NULL); + + /* + * Add before tail + * NULL <-- 3 --> 4 --> 6 --> 5 --> 2 --> 7 --> 1 --> NULL + */ + dbl_list_add_before(dll, dbl_list_tail(dll), &elements[7]); + head = dbl_list_head(dll); + tail = dbl_list_tail(dll); + + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == false); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 7); + UNIT_TEST_ASSERT(head == &elements[3]); + UNIT_TEST_ASSERT(tail == &elements[1]); + UNIT_TEST_ASSERT(head->previous == NULL); + UNIT_TEST_ASSERT(tail->previous == &elements[7]); + UNIT_TEST_ASSERT(elements[7].next == &elements[1]); + UNIT_TEST_ASSERT(elements[7].previous == &elements[2]); + UNIT_TEST_ASSERT(tail->next == NULL); + + /* + * Add after tail + * NULL <-- 3 --> 4 --> 6 --> 5 --> 2 --> 7 --> 1 --> 8 --> NULL + */ + dbl_list_add_after(dll, dbl_list_tail(dll), &elements[8]); + head = dbl_list_head(dll); + tail = dbl_list_tail(dll); + + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == false); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 8); + UNIT_TEST_ASSERT(head == &elements[3]); + UNIT_TEST_ASSERT(tail == &elements[8]); + UNIT_TEST_ASSERT(head->previous == NULL); + UNIT_TEST_ASSERT(tail->previous == &elements[1]); + UNIT_TEST_ASSERT(elements[8].next == NULL); + UNIT_TEST_ASSERT(elements[8].previous == &elements[1]); + UNIT_TEST_ASSERT(tail->next == NULL); + + /* + * Find and remove element 5 + * NULL <-- 3 --> 4 --> 6 --> 2 --> 7 --> 1 --> 8 --> NULL + */ + dbl_list_remove(dll, &elements[5]); + head = dbl_list_head(dll); + tail = dbl_list_tail(dll); + + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == false); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 7); + UNIT_TEST_ASSERT(head == &elements[3]); + UNIT_TEST_ASSERT(tail == &elements[8]); + UNIT_TEST_ASSERT(head->previous == NULL); + UNIT_TEST_ASSERT(elements[6].next == &elements[2]); + UNIT_TEST_ASSERT(elements[2].previous == &elements[6]); + UNIT_TEST_ASSERT(tail->next == NULL); + + /* + * Remove before tail + * NULL <-- 3 --> 4 --> 6 --> 2 --> 7 --> 8 --> NULL + */ + dbl_list_remove(dll, ((demo_struct_t *)dbl_list_tail(dll))->previous); + head = dbl_list_head(dll); + tail = dbl_list_tail(dll); + + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == false); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 6); + UNIT_TEST_ASSERT(head == &elements[3]); + UNIT_TEST_ASSERT(tail == &elements[8]); + UNIT_TEST_ASSERT(head->previous == NULL); + UNIT_TEST_ASSERT(elements[7].next == tail); + UNIT_TEST_ASSERT(tail->previous == &elements[7]); + UNIT_TEST_ASSERT(tail->next == NULL); + + /* + * Remove after head + * NULL <-- 3 --> 6 --> 2 --> 7 --> 8 --> NULL + */ + dbl_list_remove(dll, ((demo_struct_t *)dbl_list_head(dll))->next); + head = dbl_list_head(dll); + tail = dbl_list_tail(dll); + + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == false); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 5); + UNIT_TEST_ASSERT(head == &elements[3]); + UNIT_TEST_ASSERT(tail == &elements[8]); + UNIT_TEST_ASSERT(head->previous == NULL); + UNIT_TEST_ASSERT(head->next == &elements[6]); + UNIT_TEST_ASSERT(elements[6].previous == head); + UNIT_TEST_ASSERT(tail->next == NULL); + + /* + * Find element 2 and remove whatever is after it + * NULL <-- 3 --> 6 --> 2 --> 8 --> NULL + */ + dbl_list_remove(dll, elements[2].next); + head = dbl_list_head(dll); + tail = dbl_list_tail(dll); + + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == false); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 4); + UNIT_TEST_ASSERT(head == &elements[3]); + UNIT_TEST_ASSERT(tail == &elements[8]); + UNIT_TEST_ASSERT(head->previous == NULL); + UNIT_TEST_ASSERT(elements[2].next == tail); + UNIT_TEST_ASSERT(tail->previous == &elements[2]); + UNIT_TEST_ASSERT(tail->next == NULL); + + /* + * Find element 2 and remove whatever is before it + * NULL <-- 3 --> 2 --> 8 --> NULL + */ + dbl_list_remove(dll, elements[2].previous); + head = dbl_list_head(dll); + tail = dbl_list_tail(dll); + + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == false); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 3); + UNIT_TEST_ASSERT(head == &elements[3]); + UNIT_TEST_ASSERT(tail == &elements[8]); + UNIT_TEST_ASSERT(head->previous == NULL); + UNIT_TEST_ASSERT(head->next == &elements[2]); + UNIT_TEST_ASSERT(elements[2].previous == head); + UNIT_TEST_ASSERT(tail->next == NULL); + + /* + * Remove head + * NULL <-- 2 --> 8 --> NULL + */ + dbl_list_remove(dll, dbl_list_head(dll)); + head = dbl_list_head(dll); + tail = dbl_list_tail(dll); + + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == false); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 2); + UNIT_TEST_ASSERT(head == &elements[2]); + UNIT_TEST_ASSERT(tail == &elements[8]); + UNIT_TEST_ASSERT(head->previous == NULL); + UNIT_TEST_ASSERT(head->next == tail); + UNIT_TEST_ASSERT(tail->previous == head); + UNIT_TEST_ASSERT(tail->next == NULL); + + /* + * Remove tail + * NULL <-- 8 --> NULL + */ + dbl_list_remove(dll, dbl_list_head(dll)); + head = dbl_list_head(dll); + tail = dbl_list_tail(dll); + + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == false); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 1); + UNIT_TEST_ASSERT(head == &elements[8]); + UNIT_TEST_ASSERT(tail == &elements[8]); + UNIT_TEST_ASSERT(head->previous == NULL); + UNIT_TEST_ASSERT(head->next == NULL); + UNIT_TEST_ASSERT(tail->previous == NULL); + UNIT_TEST_ASSERT(tail->next == NULL); + + /* Remove the last element */ + dbl_list_remove(dll, dbl_list_head(dll)); + UNIT_TEST_ASSERT(dbl_list_is_empty(dll) == true); + UNIT_TEST_ASSERT(dbl_list_length(dll) == 0); + UNIT_TEST_ASSERT(dbl_list_head(dll) == NULL); + UNIT_TEST_ASSERT(dbl_list_tail(dll) == NULL); + + UNIT_TEST_END(); +} +/*---------------------------------------------------------------------------*/ +UNIT_TEST_REGISTER(test_cdll, "Circular, doubly-linked list"); +UNIT_TEST(test_cdll) +{ + demo_struct_t *head, *tail; + + CIRCULAR_LIST(cdll); + + UNIT_TEST_BEGIN(); + + memset(elements, 0, sizeof(elements)); + + /* Starts from empty */ + dbl_circ_list_init(cdll); + UNIT_TEST_ASSERT(dbl_circ_list_is_empty(cdll) == true); + UNIT_TEST_ASSERT(dbl_circ_list_length(cdll) == 0); + UNIT_TEST_ASSERT(dbl_circ_list_head(cdll) == NULL); + UNIT_TEST_ASSERT(dbl_circ_list_tail(cdll) == NULL); + + /* + * Add an item by adding to the head. + * Head and tail should be the same element and should point to itself in + * both directions + */ + dbl_circ_list_add_head(cdll, &elements[0]); + head = dbl_circ_list_head(cdll); + tail = dbl_circ_list_tail(cdll); + + UNIT_TEST_ASSERT(dbl_circ_list_is_empty(cdll) == false); + UNIT_TEST_ASSERT(dbl_circ_list_length(cdll) == 1); + UNIT_TEST_ASSERT(head == &elements[0]); + UNIT_TEST_ASSERT(tail == &elements[0]); + UNIT_TEST_ASSERT(head->previous == head); + UNIT_TEST_ASSERT(head->next == head); + UNIT_TEST_ASSERT(tail->previous == tail); + UNIT_TEST_ASSERT(tail->next == tail); + + /* + * Add an item by adding to the tail. + * (tail) <--> 0 <--> 1 <--> (head) + * Head should point to tail in both directions + */ + dbl_circ_list_add_tail(cdll, &elements[1]); + head = dbl_circ_list_head(cdll); + tail = dbl_circ_list_tail(cdll); + + UNIT_TEST_ASSERT(dbl_circ_list_is_empty(cdll) == false); + UNIT_TEST_ASSERT(dbl_circ_list_length(cdll) == 2); + UNIT_TEST_ASSERT(head == &elements[0]); + UNIT_TEST_ASSERT(tail == &elements[1]); + UNIT_TEST_ASSERT(head->next == tail); + UNIT_TEST_ASSERT(tail->previous == head); + UNIT_TEST_ASSERT(head->previous == tail); + UNIT_TEST_ASSERT(tail->next == head); + + /* + * Add before head. + * (tail) <--> 2 <--> 0 <--> 1 <--> (head) + */ + dbl_circ_list_add_before(cdll, dbl_circ_list_head(cdll), &elements[2]); + head = dbl_circ_list_head(cdll); + tail = dbl_circ_list_tail(cdll); + + UNIT_TEST_ASSERT(dbl_circ_list_is_empty(cdll) == false); + UNIT_TEST_ASSERT(dbl_circ_list_length(cdll) == 3); + UNIT_TEST_ASSERT(head == &elements[2]); + UNIT_TEST_ASSERT(tail == &elements[1]); + UNIT_TEST_ASSERT(head->previous == tail); + UNIT_TEST_ASSERT(tail->next == head); + UNIT_TEST_ASSERT(elements[2].previous == tail); + UNIT_TEST_ASSERT(elements[2].next == &elements[0]); + UNIT_TEST_ASSERT(elements[0].previous == head); + + /* + * Add after head. + * (tail) <--> 2 <--> 3 <--> 0 <--> 1 <--> (head) + */ + dbl_circ_list_add_after(cdll, dbl_circ_list_head(cdll), &elements[3]); + head = dbl_circ_list_head(cdll); + tail = dbl_circ_list_tail(cdll); + + UNIT_TEST_ASSERT(dbl_circ_list_is_empty(cdll) == false); + UNIT_TEST_ASSERT(dbl_circ_list_length(cdll) == 4); + UNIT_TEST_ASSERT(head == &elements[2]); + UNIT_TEST_ASSERT(tail == &elements[1]); + UNIT_TEST_ASSERT(head->previous == tail); + UNIT_TEST_ASSERT(tail->next == head); + UNIT_TEST_ASSERT(elements[3].previous == head); + UNIT_TEST_ASSERT(elements[3].next == &elements[0]); + UNIT_TEST_ASSERT(elements[0].previous == &elements[3]); + + /* + * Add at 3rd position by adding after 2nd + * (tail) <--> 2 <--> 3 <--> 4 <--> 0 <--> 1 <--> (head) + */ + dbl_circ_list_add_after(cdll, &elements[3], &elements[4]); + head = dbl_circ_list_head(cdll); + tail = dbl_circ_list_tail(cdll); + + UNIT_TEST_ASSERT(dbl_circ_list_is_empty(cdll) == false); + UNIT_TEST_ASSERT(dbl_circ_list_length(cdll) == 5); + UNIT_TEST_ASSERT(head == &elements[2]); + UNIT_TEST_ASSERT(tail == &elements[1]); + UNIT_TEST_ASSERT(head->previous == tail); + UNIT_TEST_ASSERT(tail->next == head); + UNIT_TEST_ASSERT(elements[3].next == &elements[4]); + UNIT_TEST_ASSERT(elements[4].previous == &elements[3]); + UNIT_TEST_ASSERT(elements[4].next == &elements[0]); + UNIT_TEST_ASSERT(elements[0].previous == &elements[4]); + + /* + * Add at 3rd position by adding before 3rd + * (tail) <--> 2 <--> 3 <--> 5 <--> 4 <--> 0 <--> 1 <--> (head) + */ + dbl_circ_list_add_before(cdll, &elements[4], &elements[5]); + head = dbl_circ_list_head(cdll); + tail = dbl_circ_list_tail(cdll); + + UNIT_TEST_ASSERT(dbl_circ_list_is_empty(cdll) == false); + UNIT_TEST_ASSERT(dbl_circ_list_length(cdll) == 6); + UNIT_TEST_ASSERT(head == &elements[2]); + UNIT_TEST_ASSERT(tail == &elements[1]); + UNIT_TEST_ASSERT(head->previous == tail); + UNIT_TEST_ASSERT(tail->next == head); + UNIT_TEST_ASSERT(elements[3].next == &elements[5]); + UNIT_TEST_ASSERT(elements[5].previous == &elements[3]); + UNIT_TEST_ASSERT(elements[5].next == &elements[4]); + UNIT_TEST_ASSERT(elements[4].previous == &elements[5]); + + /* + * Add before tail + * (tail) <--> 2 <--> 3 <--> 5 <--> 4 <--> 0 <--> 6 <--> 1 <--> (head) + */ + dbl_circ_list_add_before(cdll, dbl_circ_list_tail(cdll), &elements[6]); + head = dbl_circ_list_head(cdll); + tail = dbl_circ_list_tail(cdll); + + UNIT_TEST_ASSERT(dbl_circ_list_is_empty(cdll) == false); + UNIT_TEST_ASSERT(dbl_circ_list_length(cdll) == 7); + UNIT_TEST_ASSERT(head == &elements[2]); + UNIT_TEST_ASSERT(tail == &elements[1]); + UNIT_TEST_ASSERT(head->previous == tail); + UNIT_TEST_ASSERT(tail->next == head); + UNIT_TEST_ASSERT(elements[0].next == &elements[6]); + UNIT_TEST_ASSERT(elements[6].previous == &elements[0]); + UNIT_TEST_ASSERT(elements[6].next == &elements[1]); + UNIT_TEST_ASSERT(elements[1].previous == &elements[6]); + + /* + * Add after tail + * (tail) <--> 2 <--> 3 <--> 5 <--> 4 <--> 0 <--> 6 <--> 1 <--> 7 <--> (head) + */ + dbl_circ_list_add_after(cdll, dbl_circ_list_tail(cdll), &elements[7]); + head = dbl_circ_list_head(cdll); + tail = dbl_circ_list_tail(cdll); + + UNIT_TEST_ASSERT(dbl_circ_list_is_empty(cdll) == false); + UNIT_TEST_ASSERT(dbl_circ_list_length(cdll) == 8); + UNIT_TEST_ASSERT(head == &elements[2]); + UNIT_TEST_ASSERT(tail == &elements[7]); + UNIT_TEST_ASSERT(head->previous == tail); + UNIT_TEST_ASSERT(tail->next == head); + UNIT_TEST_ASSERT(elements[1].next == &elements[7]); + UNIT_TEST_ASSERT(elements[7].previous == &elements[1]); + UNIT_TEST_ASSERT(elements[7].next == &elements[2]); + UNIT_TEST_ASSERT(elements[2].previous == &elements[7]); + + /* + * Find and remove element 5 + * (tail) <--> 2 <--> 3 <--> 4 <--> 0 <--> 6 <--> 1 <--> 7 <--> (head) + */ + dbl_circ_list_remove(cdll, &elements[5]); + head = dbl_circ_list_head(cdll); + tail = dbl_circ_list_tail(cdll); + + UNIT_TEST_ASSERT(dbl_circ_list_is_empty(cdll) == false); + UNIT_TEST_ASSERT(dbl_circ_list_length(cdll) == 7); + UNIT_TEST_ASSERT(head == &elements[2]); + UNIT_TEST_ASSERT(tail == &elements[7]); + UNIT_TEST_ASSERT(head->previous == tail); + UNIT_TEST_ASSERT(tail->next == head); + UNIT_TEST_ASSERT(elements[3].next == &elements[4]); + UNIT_TEST_ASSERT(elements[4].previous == &elements[3]); + + /* + * Find element 4 and remove what's after it + * (tail) <--> 2 <--> 3 <--> 4 <--> 6 <--> 1 <--> 7 <--> (head) + */ + dbl_circ_list_remove(cdll, elements[4].next); + head = dbl_circ_list_head(cdll); + tail = dbl_circ_list_tail(cdll); + + UNIT_TEST_ASSERT(dbl_circ_list_is_empty(cdll) == false); + UNIT_TEST_ASSERT(dbl_circ_list_length(cdll) == 6); + UNIT_TEST_ASSERT(head == &elements[2]); + UNIT_TEST_ASSERT(tail == &elements[7]); + UNIT_TEST_ASSERT(head->previous == tail); + UNIT_TEST_ASSERT(tail->next == head); + UNIT_TEST_ASSERT(elements[4].next == &elements[6]); + UNIT_TEST_ASSERT(elements[6].previous == &elements[4]); + + /* + * Find element 4 and remove what's before it + * (tail) <--> 2 <--> 4 <--> 6 <--> 1 <--> 7 <--> (head) + */ + dbl_circ_list_remove(cdll, elements[4].previous); + head = dbl_circ_list_head(cdll); + tail = dbl_circ_list_tail(cdll); + + UNIT_TEST_ASSERT(dbl_circ_list_is_empty(cdll) == false); + UNIT_TEST_ASSERT(dbl_circ_list_length(cdll) == 5); + UNIT_TEST_ASSERT(head == &elements[2]); + UNIT_TEST_ASSERT(tail == &elements[7]); + UNIT_TEST_ASSERT(head->previous == tail); + UNIT_TEST_ASSERT(tail->next == head); + UNIT_TEST_ASSERT(elements[2].next == &elements[4]); + UNIT_TEST_ASSERT(elements[4].previous == &elements[2]); + + /* + * Remove before tail + * (tail) <--> 2 <--> 4 <--> 6 <--> 7 <--> (head) + */ + dbl_circ_list_remove(cdll, + ((demo_struct_t *)dbl_circ_list_tail(cdll))->previous); + head = dbl_circ_list_head(cdll); + tail = dbl_circ_list_tail(cdll); + + UNIT_TEST_ASSERT(dbl_circ_list_is_empty(cdll) == false); + UNIT_TEST_ASSERT(dbl_circ_list_length(cdll) == 4); + UNIT_TEST_ASSERT(head == &elements[2]); + UNIT_TEST_ASSERT(tail == &elements[7]); + UNIT_TEST_ASSERT(head->previous == tail); + UNIT_TEST_ASSERT(tail->next == head); + UNIT_TEST_ASSERT(elements[6].next == &elements[7]); + UNIT_TEST_ASSERT(elements[7].previous == &elements[6]); + + /* + * Remove after tail + * (tail) <--> 4 <--> 6 <--> 7 <--> (head) + */ + dbl_circ_list_remove(cdll, + ((demo_struct_t *)dbl_circ_list_tail(cdll))->next); + head = dbl_circ_list_head(cdll); + tail = dbl_circ_list_tail(cdll); + + UNIT_TEST_ASSERT(dbl_circ_list_is_empty(cdll) == false); + UNIT_TEST_ASSERT(dbl_circ_list_length(cdll) == 3); + UNIT_TEST_ASSERT(head == &elements[4]); + UNIT_TEST_ASSERT(tail == &elements[7]); + UNIT_TEST_ASSERT(head->previous == tail); + UNIT_TEST_ASSERT(tail->next == head); + UNIT_TEST_ASSERT(elements[7].next == &elements[4]); + UNIT_TEST_ASSERT(elements[4].previous == &elements[7]); + + /* + * Remove after head + * (tail) <--> 4 <--> 7 <--> (head) + */ + dbl_circ_list_remove(cdll, + ((demo_struct_t *)dbl_circ_list_head(cdll))->next); + head = dbl_circ_list_head(cdll); + tail = dbl_circ_list_tail(cdll); + + UNIT_TEST_ASSERT(dbl_circ_list_is_empty(cdll) == false); + UNIT_TEST_ASSERT(dbl_circ_list_length(cdll) == 2); + UNIT_TEST_ASSERT(head == &elements[4]); + UNIT_TEST_ASSERT(tail == &elements[7]); + UNIT_TEST_ASSERT(head->previous == tail); + UNIT_TEST_ASSERT(head->next == tail); + UNIT_TEST_ASSERT(tail->previous == head); + UNIT_TEST_ASSERT(tail->next == head); + + /* + * Remove before head + * (tail) <--> 4 <--> (head) + */ + dbl_circ_list_remove(cdll, + ((demo_struct_t *)dbl_circ_list_head(cdll))->previous); + head = dbl_circ_list_head(cdll); + tail = dbl_circ_list_tail(cdll); + + UNIT_TEST_ASSERT(dbl_circ_list_is_empty(cdll) == false); + UNIT_TEST_ASSERT(dbl_circ_list_length(cdll) == 1); + UNIT_TEST_ASSERT(head == &elements[4]); + UNIT_TEST_ASSERT(tail == &elements[4]); + UNIT_TEST_ASSERT(head->previous == tail); + UNIT_TEST_ASSERT(head->next == tail); + + /* Remove head */ + dbl_circ_list_remove(cdll, dbl_circ_list_head(cdll)); + dbl_circ_list_remove(cdll, dbl_circ_list_head(cdll)); + UNIT_TEST_ASSERT(dbl_circ_list_is_empty(cdll) == true); + UNIT_TEST_ASSERT(dbl_circ_list_length(cdll) == 0); + UNIT_TEST_ASSERT(dbl_circ_list_head(cdll) == NULL); + UNIT_TEST_ASSERT(dbl_circ_list_tail(cdll) == NULL); + + UNIT_TEST_END(); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(data_structure_test_process, ev, data) +{ + PROCESS_BEGIN(); + + printf("Run unit-test\n"); + printf("---\n"); + + memset(elements, 0, sizeof(elements)); + + UNIT_TEST_RUN(test_list); + UNIT_TEST_RUN(test_stack); + UNIT_TEST_RUN(test_queue); + UNIT_TEST_RUN(test_csll); + UNIT_TEST_RUN(test_dll); + UNIT_TEST_RUN(test_cdll); + + printf("=check-me= DONE\n"); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/tests/08-ipv6/code/receiver/Makefile b/tests/07-simulation-base/code-ipv6/receiver/Makefile similarity index 100% rename from tests/08-ipv6/code/receiver/Makefile rename to tests/07-simulation-base/code-ipv6/receiver/Makefile diff --git a/tests/08-ipv6/code/receiver/project-conf.h b/tests/07-simulation-base/code-ipv6/receiver/project-conf.h similarity index 100% rename from tests/08-ipv6/code/receiver/project-conf.h rename to tests/07-simulation-base/code-ipv6/receiver/project-conf.h diff --git a/tests/08-ipv6/code/receiver/udp-receiver.c b/tests/07-simulation-base/code-ipv6/receiver/udp-receiver.c similarity index 100% rename from tests/08-ipv6/code/receiver/udp-receiver.c rename to tests/07-simulation-base/code-ipv6/receiver/udp-receiver.c diff --git a/tests/08-ipv6/code/sender/Makefile b/tests/07-simulation-base/code-ipv6/sender/Makefile similarity index 100% rename from tests/08-ipv6/code/sender/Makefile rename to tests/07-simulation-base/code-ipv6/sender/Makefile diff --git a/tests/08-ipv6/code/sender/project-conf.h b/tests/07-simulation-base/code-ipv6/sender/project-conf.h similarity index 100% rename from tests/08-ipv6/code/sender/project-conf.h rename to tests/07-simulation-base/code-ipv6/sender/project-conf.h diff --git a/tests/08-ipv6/code/sender/udp-sender.c b/tests/07-simulation-base/code-ipv6/sender/udp-sender.c similarity index 100% rename from tests/08-ipv6/code/sender/udp-sender.c rename to tests/07-simulation-base/code-ipv6/sender/udp-sender.c diff --git a/tests/08-ipv6/code/sender/unicast-sender.c b/tests/07-simulation-base/code-ipv6/sender/unicast-sender.c similarity index 95% rename from tests/08-ipv6/code/sender/unicast-sender.c rename to tests/07-simulation-base/code-ipv6/sender/unicast-sender.c index 929e0d584f49087f9514a2da31444bb429973ae3..4e2e664b343ba9dbbd85c595818a7890a650867f 100644 --- a/tests/08-ipv6/code/sender/unicast-sender.c +++ b/tests/07-simulation-base/code-ipv6/sender/unicast-sender.c @@ -1,8 +1,7 @@ #include "contiki.h" #include "contiki-lib.h" #include "contiki-net.h" -#include "rpl.h" -#include "rpl-dag-root.h" +#include "net/routing/routing.h" #include <stdio.h> @@ -41,7 +40,7 @@ PROCESS_THREAD(udp_process, ev, data) PROCESS_BEGIN(); - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_start(); simple_udp_register(&broadcast_connection, UDP_PORT, NULL, UDP_PORT, diff --git a/tests/07-base/code/Makefile b/tests/07-simulation-base/code-ringbufindex/Makefile similarity index 100% rename from tests/07-base/code/Makefile rename to tests/07-simulation-base/code-ringbufindex/Makefile diff --git a/tests/07-base/code/project-conf.h b/tests/07-simulation-base/code-ringbufindex/project-conf.h similarity index 95% rename from tests/07-base/code/project-conf.h rename to tests/07-simulation-base/code-ringbufindex/project-conf.h index a7683dbb51a70b7ceefad632d64e02a5c458c0dc..e745536d9413f753ed3b734aeb18f9ec26c21aee 100644 --- a/tests/07-base/code/project-conf.h +++ b/tests/07-simulation-base/code-ringbufindex/project-conf.h @@ -29,9 +29,9 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _PROJECT_CONF_H_ -#define _PROJECT_CONF_H_ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ #define UNIT_TEST_PRINT_FUNCTION test_print_report -#endif /* !_PROJECT_CONF_H_ */ +#endif /* !PROJECT_CONF_H_ */ diff --git a/tests/07-base/code/test-ringbufindex.c b/tests/07-simulation-base/code-ringbufindex/test-ringbufindex.c similarity index 100% rename from tests/07-base/code/test-ringbufindex.c rename to tests/07-simulation-base/code-ringbufindex/test-ringbufindex.c diff --git a/tests/08-ipv6/code-slip-radio/Makefile b/tests/07-simulation-base/code-slip-radio/Makefile similarity index 100% rename from tests/08-ipv6/code-slip-radio/Makefile rename to tests/07-simulation-base/code-slip-radio/Makefile diff --git a/tests/07-simulation-base/code-slip-radio/project-conf.h b/tests/07-simulation-base/code-slip-radio/project-conf.h new file mode 100644 index 0000000000000000000000000000000000000000..e8af03208b351917c84dab409184631b606510db --- /dev/null +++ b/tests/07-simulation-base/code-slip-radio/project-conf.h @@ -0,0 +1,6 @@ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#define RPL_CONF_DAO_ACK 1 + +#endif /* PROJECT_CONF_H_ */ diff --git a/tests/08-ipv6/code-slip-radio/wait-dag.c b/tests/07-simulation-base/code-slip-radio/wait-dag.c similarity index 96% rename from tests/08-ipv6/code-slip-radio/wait-dag.c rename to tests/07-simulation-base/code-slip-radio/wait-dag.c index 83e3d28f7cacf0d8657c8e56c6904a9f0733fa92..a059661b4f0f9c34c723150b19ece936ce660e35 100644 --- a/tests/08-ipv6/code-slip-radio/wait-dag.c +++ b/tests/07-simulation-base/code-slip-radio/wait-dag.c @@ -33,7 +33,7 @@ #include "contiki.h" #include "contiki-lib.h" #include "contiki-net.h" -#include "rpl.h" +#include "net/routing/routing.h" #include "net/ipv6/uip.h" #include <string.h> @@ -49,8 +49,7 @@ AUTOSTART_PROCESSES(&wait_for_dag); static void timeout_handler(void) { - rpl_dag_t *dag = rpl_get_any_dag(); - if (dag != NULL) { + if(NETSTACK_ROUTING.node_has_joined()) { PRINTF("DAG Found\n"); } } @@ -67,7 +66,7 @@ PROCESS_THREAD(wait_for_dag, ev, data) if(etimer_expired(&et)) { timeout_handler(); etimer_restart(&et); - } + } } PROCESS_END(); } diff --git a/tests/07-base/js/04-ringbufindex.js b/tests/07-simulation-base/js/04-ringbufindex.js similarity index 98% rename from tests/07-base/js/04-ringbufindex.js rename to tests/07-simulation-base/js/04-ringbufindex.js index 153f920af0969411537ba199190c5b19fff8b165..5acb27f11b74aa4d74a195f97c29845c33c52555 100644 --- a/tests/07-base/js/04-ringbufindex.js +++ b/tests/07-simulation-base/js/04-ringbufindex.js @@ -6,7 +6,7 @@ while(true) { YIELD(); log.log(time + " " + "node-" + id + " "+ msg + "\n"); - + if(msg.contains("=check-me=") == false) { continue; } @@ -23,4 +23,3 @@ if(failed) { log.testFailed(); } log.testOK(); - diff --git a/tests/07-simulation-base/js/22-stack-check.js b/tests/07-simulation-base/js/22-stack-check.js new file mode 100644 index 0000000000000000000000000000000000000000..3dd0b381c6d5fbc01fe0ecfa6ee66a741a76c740 --- /dev/null +++ b/tests/07-simulation-base/js/22-stack-check.js @@ -0,0 +1,25 @@ +TIMEOUT(100000); + +/* This script checks that the stack usage is dynamically changing */ + +var re = /stack usage: (\d+)/i; + +var minusage = 10000; +var maxusage = 0; + +while(true) { + log.log("> " + msg + "\n"); + + var found = msg.match(re); + + if(found) { + var n = parseInt(found[1]); + minusage = minusage < n ? minusage : n; + maxusage = maxusage > n ? maxusage : n; + + if(minusage < 800 && maxusage >= 1000) { + log.testOK(); + } + } + YIELD(); +} diff --git a/tests/07-simulation-base/js/data-structures.js b/tests/07-simulation-base/js/data-structures.js new file mode 100644 index 0000000000000000000000000000000000000000..5acb27f11b74aa4d74a195f97c29845c33c52555 --- /dev/null +++ b/tests/07-simulation-base/js/data-structures.js @@ -0,0 +1,25 @@ +TIMEOUT(10000, log.testFailed()); + +var failed = false; + +while(true) { + YIELD(); + + log.log(time + " " + "node-" + id + " "+ msg + "\n"); + + if(msg.contains("=check-me=") == false) { + continue; + } + + if(msg.contains("FAILED")) { + failed = true; + } + + if(msg.contains("DONE")) { + break; + } +} +if(failed) { + log.testFailed(); +} +log.testOK(); diff --git a/tests/07-base/hello-world.js b/tests/07-simulation-base/js/hello-world.js similarity index 100% rename from tests/07-base/hello-world.js rename to tests/07-simulation-base/js/hello-world.js diff --git a/tests/08-ipv6/02-sky-slip-radio.csc b/tests/08-ipv6/02-sky-slip-radio.csc deleted file mode 100644 index 35f4c95accf0ff2335f4c68e5b06e38f8dcc0964..0000000000000000000000000000000000000000 --- a/tests/08-ipv6/02-sky-slip-radio.csc +++ /dev/null @@ -1,189 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<simconf> - <project EXPORT="discard">[APPS_DIR]/mrm</project> - <project EXPORT="discard">[APPS_DIR]/mspsim</project> - <project EXPORT="discard">[APPS_DIR]/avrora</project> - <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> - <project EXPORT="discard">[APPS_DIR]/powertracker</project> - <simulation> - <title>slip radio 1</title> - <randomseed>123456</randomseed> - <motedelay_us>1000000</motedelay_us> - <radiomedium> - se.sics.cooja.radiomediums.UDGM - <transmitting_range>15.0</transmitting_range> - <interference_range>15.0</interference_range> - <success_ratio_tx>1.0</success_ratio_tx> - <success_ratio_rx>1.0</success_ratio_rx> - </radiomedium> - <events> - <logoutput>40000</logoutput> - </events> - <motetype> - se.sics.cooja.mspmote.SkyMoteType - <identifier>sky1</identifier> - <description>slip radio</description> - <source EXPORT="discard">[CONTIKI_DIR]/examples/slip-radio/slip-radio.c</source> - <commands EXPORT="discard">make slip-radio.sky TARGET=sky</commands> - <firmware EXPORT="copy">[CONTIKI_DIR]/examples/slip-radio/slip-radio.sky</firmware> - <moteinterface>se.sics.cooja.interfaces.Position</moteinterface> - <moteinterface>se.sics.cooja.interfaces.RimeAddress</moteinterface> - <moteinterface>se.sics.cooja.interfaces.IPAddress</moteinterface> - <moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface> - <moteinterface>se.sics.cooja.interfaces.MoteAttributes</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.MspClock</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.MspMoteID</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.SkyButton</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.SkyFlash</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.Msp802154Radio</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.MspSerial</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.SkyLED</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.MspDebugOutput</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.SkyTemperature</moteinterface> - </motetype> - <motetype> - se.sics.cooja.mspmote.SkyMoteType - <identifier>sky2</identifier> - <description>wait-dag</description> - <source EXPORT="discard">[CONFIG_DIR]/code-slip-radio/wait-dag.c</source> - <commands EXPORT="discard">make wait-dag.sky TARGET=sky</commands> - <firmware EXPORT="copy">[CONFIG_DIR]/code-slip-radio/wait-dag.sky</firmware> - <moteinterface>se.sics.cooja.interfaces.Position</moteinterface> - <moteinterface>se.sics.cooja.interfaces.RimeAddress</moteinterface> - <moteinterface>se.sics.cooja.interfaces.IPAddress</moteinterface> - <moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface> - <moteinterface>se.sics.cooja.interfaces.MoteAttributes</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.MspClock</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.MspMoteID</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.SkyButton</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.SkyFlash</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.Msp802154Radio</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.MspSerial</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.SkyLED</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.MspDebugOutput</moteinterface> - <moteinterface>se.sics.cooja.mspmote.interfaces.SkyTemperature</moteinterface> - </motetype> - <mote> - <breakpoints /> - <interface_config> - se.sics.cooja.interfaces.Position - <x>43.565500781711165</x> - <y>14.697933087406794</y> - <z>0.0</z> - </interface_config> - <interface_config> - se.sics.cooja.mspmote.interfaces.MspMoteID - <id>1</id> - </interface_config> - <motetype_identifier>sky1</motetype_identifier> - </mote> - <mote> - <breakpoints /> - <interface_config> - se.sics.cooja.interfaces.Position - <x>53.849666651434326</x> - <y>14.629826028666905</y> - <z>0.0</z> - </interface_config> - <interface_config> - se.sics.cooja.mspmote.interfaces.MspMoteID - <id>2</id> - </interface_config> - <motetype_identifier>sky2</motetype_identifier> - </mote> - </simulation> - <plugin> - se.sics.cooja.plugins.SimControl - <width>315</width> - <z>1</z> - <height>175</height> - <location_x>433</location_x> - <location_y>0</location_y> - </plugin> - <plugin> - se.sics.cooja.plugins.Visualizer - <plugin_config> - <skin>se.sics.cooja.plugins.skins.IDVisualizerSkin</skin> - <skin>se.sics.cooja.plugins.skins.GridVisualizerSkin</skin> - <skin>se.sics.cooja.plugins.skins.TrafficVisualizerSkin</skin> - <skin>se.sics.cooja.plugins.skins.UDGMVisualizerSkin</skin> - <viewport>14.682765905648006 0.0 0.0 14.682765905648006 -512.6620495401903 -96.80631081927221</viewport> - </plugin_config> - <width>432</width> - <z>4</z> - <height>291</height> - <location_x>1</location_x> - <location_y>1</location_y> - </plugin> - <plugin> - se.sics.cooja.plugins.LogListener - <plugin_config> - <filter /> - </plugin_config> - <width>758</width> - <z>3</z> - <height>289</height> - <location_x>748</location_x> - <location_y>159</location_y> - </plugin> - <plugin> - se.sics.cooja.plugins.Notes - <plugin_config> - <notes>Slip-radio Tests, 01-sky-slip-radio-dio - -Test that we can send a packet over a slip-radio. -In this basic test, we send a DIO from mote 1, and wait for "DAG Found" in mote 2.</notes> - <decorations>true</decorations> - </plugin_config> - <width>928</width> - <z>5</z> - <height>159</height> - <location_x>749</location_x> - <location_y>-1</location_y> - </plugin> - <plugin> - se.sics.cooja.plugins.ScriptRunner - <plugin_config> - <script>TIMEOUT(30000, log.log("last msg: " + msg + "\n")); /* print last msg at timeout */ - -YIELD_THEN_WAIT_UNTIL(msg.contains("Slip Radio started...")); - -//Wait for 5 sec -GENERATE_MSG(5000, "sleep"); -YIELD_THEN_WAIT_UNTIL(msg.equals("sleep")); - -//Configure 802.15.4 Channel (checks that we can detect commands on serial input) -write(sim.getMoteWithID(1), String.fromCharCode(0x21,67,26,192)); -YIELD_THEN_WAIT_UNTIL(msg.contains("setting channel: 26")); - -/*Send a DIO over SLIP with !S... ugly, but enough to test the radio - note: 192 = SLIP_END */ -write(sim.getMoteWithID(1), String.fromCharCode(192,0x21,0x53,0x1,0x2,0x6,0x0,0xd0,0x7,0x0,0x1,0x41,0xc8,0xd0,0xcd,0xab,0xff,0xff,0x1,0x1,0x1,0x0,0x1,0x74,0x12,0x0,0x7a,0x1b,0x3a,0x4,0x1,0x0,0xff,0xff,0x1,0x1,0x1,0x1a,0x9b,0x1,0x2c,0x7c,0xa0,0x78,0x1,0x0,0x08,0xf0,0x0,0x0,0xfe,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x2,0x12,0x74,0x1,0x0,0x1,0x1,0x1,0x2,0x6,0x7,0x4,0x0,0x2,0x0,0x0,0x4,0xe,0x0,0x8,0xc,0xa,0x7,0x0,0x1,0x0,0x0,0x1,0x0,0x1e,0x1,0x0,0x8,0x1e,0x40,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xaa,0xaa,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,192)); - -//Check that the other mote receives the DIO and joins the DAG -YIELD_THEN_WAIT_UNTIL(msg.equals("DAG Found")); - -log.testOK();</script> - <active>true</active> - </plugin_config> - <width>758</width> - <z>2</z> - <height>502</height> - <location_x>749</location_x> - <location_y>449</location_y> - </plugin> - <plugin> - se.sics.cooja.plugins.RadioLogger - <plugin_config> - <split>150</split> - </plugin_config> - <width>746</width> - <z>0</z> - <height>657</height> - <location_x>3</location_x> - <location_y>294</location_y> - </plugin> -</simconf> diff --git a/tests/08-ipv6/Makefile b/tests/08-ipv6/Makefile deleted file mode 100644 index 272bc7da157d96c1a0640317971c1897e31a9f1a..0000000000000000000000000000000000000000 --- a/tests/08-ipv6/Makefile +++ /dev/null @@ -1 +0,0 @@ -include ../Makefile.simulation-test diff --git a/tests/08-ipv6/code-slip-radio/project-conf.h b/tests/08-ipv6/code-slip-radio/project-conf.h deleted file mode 100644 index 616601c1c450866ec11d03481b14026c33332537..0000000000000000000000000000000000000000 --- a/tests/08-ipv6/code-slip-radio/project-conf.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __PROJECT_CONF_H__ -#define __PROJECT_CONF_H__ - -#define RPL_CONF_DAO_ACK 1 - -#endif /* __PROJECT_CONF_H__ */ diff --git a/tests/08-ipv6/fragmentation-should-receive-all.js b/tests/08-ipv6/fragmentation-should-receive-all.js deleted file mode 100644 index b6ad2dbd8550140964690c7580390f9238265233..0000000000000000000000000000000000000000 --- a/tests/08-ipv6/fragmentation-should-receive-all.js +++ /dev/null @@ -1,23 +0,0 @@ -TIMEOUT(200000, log.log("last message: " + msg + "\n")); - -data = 0; -alive = 0; -while(true) { - YIELD(); - if(msg.startsWith('Data')) { - data++; - log.log("Heard " + data + " data messages\n"); - } - if(msg.startsWith('Alive')) { - alive++; - log.log("Heard " + alive + " alive messages\n"); - } - if(data == 10 && alive == 10) { - if(msg.startsWith('Data 10') || - msg.startsWith('Alive 10')) { - log.testOK(); - } else { - log.testError(); - } - } -} diff --git a/tests/08-ipv6/fragmentation-should-receive-none.js b/tests/08-ipv6/fragmentation-should-receive-none.js deleted file mode 100644 index 6a04bbf4f0a6c2562f0eed30f582c15dbcfb4d8b..0000000000000000000000000000000000000000 --- a/tests/08-ipv6/fragmentation-should-receive-none.js +++ /dev/null @@ -1,22 +0,0 @@ -TIMEOUT(200000, log.log("last message: " + msg + "\n")); - -data = 0; -alive = 0; -while(true) { - YIELD(); - if(msg.startsWith('Data')) { - data++; - log.log("Heard " + data + " data messages\n"); - } - if(msg.startsWith('Alive')) { - alive++; - log.log("Heard " + alive + " alive messages\n"); - } - if(data == 0 && alive == 10) { - if(msg.startsWith('Alive 10')) { - log.testOK(); - } else { - log.testError(); - } - } -} diff --git a/tests/08-native-runs/01-test-data-structures.sh b/tests/08-native-runs/01-test-data-structures.sh new file mode 100755 index 0000000000000000000000000000000000000000..7902356387837d49db169ef54868f9f11d113ec2 --- /dev/null +++ b/tests/08-native-runs/01-test-data-structures.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 + +# Example code directory +CODE_DIR=$CONTIKI/tests/07-simulation-base/code-data-structures/ +CODE=test-data-structures + +# Starting Contiki-NG native node +echo "Starting native node" +make -C $CODE_DIR TARGET=native > make.log 2> make.err +$CODE_DIR/$CODE.native > $CODE.log 2> $CODE.err & +CPID=$! +sleep 2 + +echo "Closing native node" +sleep 2 +pgrep $CODE | xargs kill -9 + +if grep -q "=check-me= FAILED" $CODE.log ; then + echo "==== make.log ====" ; cat make.log; + echo "==== make.err ====" ; cat make.err; + echo "==== $CODE.log ====" ; cat $CODE.log; + echo "==== $CODE.err ====" ; cat $CODE.err; + + printf "%-32s TEST FAIL\n" "$CODE" | tee $CODE.testlog; +else + cp $CODE.log $CODE.testlog + printf "%-32s TEST OK\n" "$CODE" | tee $CODE.testlog; +fi + +rm make.log +rm make.err +rm $CODE.log +rm $CODE.err + +# We do not want Make to stop -> Return 0 +# The Makefile will check if a log contains FAIL at the end +exit 0 diff --git a/tests/08-native-runs/Makefile b/tests/08-native-runs/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c46e5271d5a3d2374a99b4d70b09ac5e8870495b --- /dev/null +++ b/tests/08-native-runs/Makefile @@ -0,0 +1 @@ +include ../Makefile.script-test diff --git a/tests/09-nullnet/Makefile b/tests/09-nullnet/Makefile deleted file mode 100644 index 272bc7da157d96c1a0640317971c1897e31a9f1a..0000000000000000000000000000000000000000 --- a/tests/09-nullnet/Makefile +++ /dev/null @@ -1 +0,0 @@ -include ../Makefile.simulation-test diff --git a/tests/13-ieee802154/01-panid-handling.csc b/tests/13-ieee802154/01-panid-handling.csc index ed4be25b8f0ae81fc11da21a87d33a4f690e6c0a..71ec8581857b0a717b32d3f6bf810c6293a5ab9e 100644 --- a/tests/13-ieee802154/01-panid-handling.csc +++ b/tests/13-ieee802154/01-panid-handling.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <project EXPORT="discard">[APPS_DIR]/radiologger-headless</project> <simulation> @@ -25,8 +24,8 @@ org.contikios.cooja.contikimote.ContikiMoteType <identifier>mtype740</identifier> <description>Cooja Mote Type #1</description> - <source>[CONFIG_DIR]/code/test-panid-handling.c</source> - <commands>make test-panid-handling.cooja TARGET=cooja</commands> + <source>[CONFIG_DIR]/code-panid-handling/test-panid-handling.c</source> + <commands>make -j test-panid-handling.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> diff --git a/tests/13-ieee802154/02-tsch-flush-nbr-queue.csc b/tests/13-ieee802154/02-tsch-flush-nbr-queue.csc index a7d326a25931bfc17667f4b7b71adf1a92f39fb7..879b31345634b1b340ba237a927b1bb8d31c8598 100644 --- a/tests/13-ieee802154/02-tsch-flush-nbr-queue.csc +++ b/tests/13-ieee802154/02-tsch-flush-nbr-queue.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -25,7 +24,7 @@ <identifier>mtype476</identifier> <description>Cooja Mote Type #1</description> <source>[CONFIG_DIR]/code-flush-nbr-queue/test-flush-nbr-queue.c</source> - <commands>make test-flush-nbr-queue.cooja TARGET=cooja</commands> + <commands>make -j test-flush-nbr-queue.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> diff --git a/tests/16-6tisch/05-cooja-test-sixp.csc b/tests/13-ieee802154/03-cooja-test-sixtop.csc similarity index 96% rename from tests/16-6tisch/05-cooja-test-sixp.csc rename to tests/13-ieee802154/03-cooja-test-sixtop.csc index 823af827190c25471ca756d9f1678b865c8549ab..9d5be006c01b22f058afe57fb8d2d2da69d609e9 100644 --- a/tests/16-6tisch/05-cooja-test-sixp.csc +++ b/tests/13-ieee802154/03-cooja-test-sixtop.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -24,9 +23,9 @@ org.contikios.cooja.contikimote.ContikiMoteType <identifier>mtype382</identifier> <description>Cooja Mote Type #1</description> - <source>[CONTIKI_DIR]/tests/16-6tisch/code/test-sixp.c</source> + <source>[CONFIG_DIR]/code-6tisch/test-sixtop.c</source> <commands>make clean TARGET=cooja - make test-sixp.cooja TARGET=cooja</commands> + make -j test-sixtop.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -150,7 +149,7 @@ <plugin> org.contikios.cooja.plugins.ScriptRunner <plugin_config> - <scriptfile>[CONTIKI_DIR]/tests/16-6tisch/js/unit-test.js</scriptfile> + <scriptfile>[CONFIG_DIR]/js/sixtop-test.js</scriptfile> <active>true</active> </plugin_config> <width>495</width> @@ -160,4 +159,3 @@ <location_y>105</location_y> </plugin> </simconf> - diff --git a/tests/16-6tisch/01-cooja-test-sixtop.csc b/tests/13-ieee802154/04-cooja-test-sixp-pkt.csc similarity index 96% rename from tests/16-6tisch/01-cooja-test-sixtop.csc rename to tests/13-ieee802154/04-cooja-test-sixp-pkt.csc index 3e1287b8e0e1621a4afd3b840baa3dcf563688c5..5d5cf701673417c3d242e5e5e313dab96b115888 100644 --- a/tests/16-6tisch/01-cooja-test-sixtop.csc +++ b/tests/13-ieee802154/04-cooja-test-sixp-pkt.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -24,9 +23,9 @@ org.contikios.cooja.contikimote.ContikiMoteType <identifier>mtype382</identifier> <description>Cooja Mote Type #1</description> - <source>[CONTIKI_DIR]/tests/16-6tisch/code/test-sixtop.c</source> + <source>[CONFIG_DIR]/code-6tisch/test-sixp-pkt.c</source> <commands>make clean TARGET=cooja - make test-sixtop.cooja TARGET=cooja</commands> + make -j test-sixp-pkt.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -150,7 +149,7 @@ <plugin> org.contikios.cooja.plugins.ScriptRunner <plugin_config> - <scriptfile>[CONTIKI_DIR]/tests/16-6tisch/js/unit-test.js</scriptfile> + <scriptfile>[CONFIG_DIR]/js/sixtop-test.js</scriptfile> <active>true</active> </plugin_config> <width>495</width> @@ -160,4 +159,3 @@ <location_y>105</location_y> </plugin> </simconf> - diff --git a/tests/16-6tisch/02-cooja-test-sixp-pkt.csc b/tests/13-ieee802154/05-cooja-test-sixp-trans.csc similarity index 96% rename from tests/16-6tisch/02-cooja-test-sixp-pkt.csc rename to tests/13-ieee802154/05-cooja-test-sixp-trans.csc index a410ffd6c261fa0f8aba67efbffea739d260a054..837fcc3213fce58007ed2571f7264491e2e13266 100644 --- a/tests/16-6tisch/02-cooja-test-sixp-pkt.csc +++ b/tests/13-ieee802154/05-cooja-test-sixp-trans.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -24,9 +23,9 @@ org.contikios.cooja.contikimote.ContikiMoteType <identifier>mtype382</identifier> <description>Cooja Mote Type #1</description> - <source>[CONTIKI_DIR]/tests/16-6tisch/code/test-sixp-pkt.c</source> + <source>[CONFIG_DIR]/code-6tisch/test-sixp-trans.c</source> <commands>make clean TARGET=cooja - make test-sixp-pkt.cooja TARGET=cooja</commands> + make -j test-sixp-trans.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -150,7 +149,7 @@ <plugin> org.contikios.cooja.plugins.ScriptRunner <plugin_config> - <scriptfile>[CONTIKI_DIR]/tests/16-6tisch/js/unit-test.js</scriptfile> + <scriptfile>[CONFIG_DIR]/js/sixtop-test.js</scriptfile> <active>true</active> </plugin_config> <width>495</width> @@ -160,4 +159,3 @@ <location_y>105</location_y> </plugin> </simconf> - diff --git a/tests/16-6tisch/04-cooja-test-sixp-nbr.csc b/tests/13-ieee802154/06-cooja-test-sixp-nbr.csc similarity index 96% rename from tests/16-6tisch/04-cooja-test-sixp-nbr.csc rename to tests/13-ieee802154/06-cooja-test-sixp-nbr.csc index cf2076e9e4bf02ab0d10037ba056e9093e283718..bbffc18a82d805a11a65e87fb0a38038be5981e3 100644 --- a/tests/16-6tisch/04-cooja-test-sixp-nbr.csc +++ b/tests/13-ieee802154/06-cooja-test-sixp-nbr.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -24,9 +23,9 @@ org.contikios.cooja.contikimote.ContikiMoteType <identifier>mtype382</identifier> <description>Cooja Mote Type #1</description> - <source>[CONTIKI_DIR]/tests/16-6tisch/code/test-sixp-nbr.c</source> + <source>[CONFIG_DIR]/code-6tisch/test-sixp-nbr.c</source> <commands>make clean TARGET=cooja - make test-sixp-nbr.cooja TARGET=cooja</commands> + make -j test-sixp-nbr.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -150,7 +149,7 @@ <plugin> org.contikios.cooja.plugins.ScriptRunner <plugin_config> - <scriptfile>[CONTIKI_DIR]/tests/16-6tisch/js/unit-test.js</scriptfile> + <scriptfile>[CONFIG_DIR]/js/sixtop-test.js</scriptfile> <active>true</active> </plugin_config> <width>495</width> @@ -160,4 +159,3 @@ <location_y>105</location_y> </plugin> </simconf> - diff --git a/tests/13-ieee802154/07-cooja-test-sixp.csc b/tests/13-ieee802154/07-cooja-test-sixp.csc new file mode 100644 index 0000000000000000000000000000000000000000..3e884e4b210fd5951ec4dc88f8469ddd4a181bdc --- /dev/null +++ b/tests/13-ieee802154/07-cooja-test-sixp.csc @@ -0,0 +1,161 @@ +<?xml version="1.0" encoding="UTF-8"?> +<simconf> + <project EXPORT="discard">[APPS_DIR]/mrm</project> + <project EXPORT="discard">[APPS_DIR]/mspsim</project> + <project EXPORT="discard">[APPS_DIR]/avrora</project> + <project EXPORT="discard">[APPS_DIR]/serial_socket</project> + <project EXPORT="discard">[APPS_DIR]/powertracker</project> + <simulation> + <title>My simulation</title> + <randomseed>123456</randomseed> + <motedelay_us>1000000</motedelay_us> + <radiomedium> + org.contikios.cooja.radiomediums.UDGM + <transmitting_range>50.0</transmitting_range> + <interference_range>100.0</interference_range> + <success_ratio_tx>1.0</success_ratio_tx> + <success_ratio_rx>1.0</success_ratio_rx> + </radiomedium> + <events> + <logoutput>40000</logoutput> + </events> + <motetype> + org.contikios.cooja.contikimote.ContikiMoteType + <identifier>mtype382</identifier> + <description>Cooja Mote Type #1</description> + <source>[CONFIG_DIR]/code-6tisch/test-sixp.c</source> + <commands>make clean TARGET=cooja + make -j test-sixp.cooja TARGET=cooja</commands> + <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> + <symbols>false</symbols> + </motetype> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>47.60131881808453</x> + <y>20.028921031789082</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>1</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> + </interface_config> + <motetype_identifier>mtype382</motetype_identifier> + </mote> + </simulation> + <plugin> + org.contikios.cooja.plugins.SimControl + <width>280</width> + <z>5</z> + <height>160</height> + <location_x>400</location_x> + <location_y>0</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.Visualizer + <plugin_config> + <moterelations>true</moterelations> + <skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin> + <skin>org.contikios.cooja.plugins.skins.GridVisualizerSkin</skin> + <skin>org.contikios.cooja.plugins.skins.TrafficVisualizerSkin</skin> + <skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin> + <viewport>0.9090909090909091 0.0 0.0 0.9090909090909091 150.72607380174134 154.79188997110083</viewport> + </plugin_config> + <width>400</width> + <z>4</z> + <height>400</height> + <location_x>1</location_x> + <location_y>1</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.LogListener + <plugin_config> + <filter /> + <formatted_time /> + <coloring /> + </plugin_config> + <width>1320</width> + <z>3</z> + <height>240</height> + <location_x>400</location_x> + <location_y>160</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.TimeLine + <plugin_config> + <mote>0</mote> + <showRadioRXTX /> + <showRadioHW /> + <showLEDs /> + <zoomfactor>500.0</zoomfactor> + </plugin_config> + <width>1720</width> + <z>2</z> + <height>166</height> + <location_x>0</location_x> + <location_y>957</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.Notes + <plugin_config> + <notes>Enter notes here</notes> + <decorations>true</decorations> + </plugin_config> + <width>1040</width> + <z>1</z> + <height>160</height> + <location_x>680</location_x> + <location_y>0</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.RadioLogger + <plugin_config> + <split>150</split> + <formatted_time /> + <showdups>false</showdups> + <hidenodests>false</hidenodests> + <analyzers name="6lowpan-pcap" /> + </plugin_config> + <width>500</width> + <z>0</z> + <height>300</height> + <location_x>290</location_x> + <location_y>422</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.ScriptRunner + <plugin_config> + <scriptfile>[CONFIG_DIR]/js/sixtop-test.js</scriptfile> + <active>true</active> + </plugin_config> + <width>495</width> + <z>0</z> + <height>525</height> + <location_x>663</location_x> + <location_y>105</location_y> + </plugin> +</simconf> diff --git a/tests/16-6tisch/code/Makefile b/tests/13-ieee802154/code-6tisch/Makefile similarity index 100% rename from tests/16-6tisch/code/Makefile rename to tests/13-ieee802154/code-6tisch/Makefile diff --git a/tests/16-6tisch/code/common.c b/tests/13-ieee802154/code-6tisch/common.c similarity index 100% rename from tests/16-6tisch/code/common.c rename to tests/13-ieee802154/code-6tisch/common.c diff --git a/tests/16-6tisch/code/common.h b/tests/13-ieee802154/code-6tisch/common.h similarity index 100% rename from tests/16-6tisch/code/common.h rename to tests/13-ieee802154/code-6tisch/common.h diff --git a/tests/16-6tisch/code/project-conf.h b/tests/13-ieee802154/code-6tisch/project-conf.h similarity index 96% rename from tests/16-6tisch/code/project-conf.h rename to tests/13-ieee802154/code-6tisch/project-conf.h index 657244d5a657d2f87d86c0a7bb8e22dc3675775a..acf60cbab8bfd1ee2e2198561f3dd410fa78567f 100644 --- a/tests/16-6tisch/code/project-conf.h +++ b/tests/13-ieee802154/code-6tisch/project-conf.h @@ -28,8 +28,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _PROJECT_CONF_H_ -#define _PROJECT_CONF_H_ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ #define SIXTOP_CONF_MAX_SCHEDULING_FUNCTIONS 2 @@ -52,4 +52,4 @@ /* Custom MAC layer */ #define NETSTACK_CONF_MAC test_mac_driver -#endif /* __PROJECT_CONF_H__ */ +#endif /* PROJECT_CONF_H_ */ diff --git a/tests/16-6tisch/code/test-sixp-nbr.c b/tests/13-ieee802154/code-6tisch/test-sixp-nbr.c similarity index 81% rename from tests/16-6tisch/code/test-sixp-nbr.c rename to tests/13-ieee802154/code-6tisch/test-sixp-nbr.c index 3bbd57a1697f657ffb0f19f812920a347679f6b4..f3c3aaab424054d249b113c8f038efa09468601a 100644 --- a/tests/16-6tisch/code/test-sixp-nbr.c +++ b/tests/13-ieee802154/code-6tisch/test-sixp-nbr.c @@ -103,51 +103,6 @@ UNIT_TEST(test_alloc_and_free) UNIT_TEST_END(); } -UNIT_TEST_REGISTER(test_gen_management, - "test GEN Management"); -UNIT_TEST(test_gen_management) -{ - sixp_nbr_t *nbr; - - UNIT_TEST_BEGIN(); - test_setup(); - - UNIT_TEST_ASSERT((nbr = sixp_nbr_alloc(&peer_addr_1)) != NULL); - UNIT_TEST_ASSERT(sixp_nbr_get_gen(nbr) == 0x00); - - UNIT_TEST_ASSERT(sixp_nbr_advance_gen(nbr) == 0); - UNIT_TEST_ASSERT(sixp_nbr_get_gen(nbr) == 0x01); - - UNIT_TEST_ASSERT(sixp_nbr_advance_gen(nbr) == 0); - UNIT_TEST_ASSERT(sixp_nbr_get_gen(nbr) == 0x02); - - UNIT_TEST_ASSERT(sixp_nbr_advance_gen(nbr) == 0); - UNIT_TEST_ASSERT(sixp_nbr_get_gen(nbr) == 0x03); - - UNIT_TEST_ASSERT(sixp_nbr_advance_gen(nbr) == 0); - UNIT_TEST_ASSERT(sixp_nbr_get_gen(nbr) == 0x04); - - UNIT_TEST_ASSERT(sixp_nbr_advance_gen(nbr) == 0); - UNIT_TEST_ASSERT(sixp_nbr_get_gen(nbr) == 0x05); - - UNIT_TEST_ASSERT(sixp_nbr_advance_gen(nbr) == 0); - UNIT_TEST_ASSERT(sixp_nbr_get_gen(nbr) == 0x06); - - UNIT_TEST_ASSERT(sixp_nbr_advance_gen(nbr) == 0); - UNIT_TEST_ASSERT(sixp_nbr_get_gen(nbr) == 0x07); - - UNIT_TEST_ASSERT(sixp_nbr_advance_gen(nbr) == 0); - UNIT_TEST_ASSERT(sixp_nbr_get_gen(nbr) == 0x08); - - UNIT_TEST_ASSERT(sixp_nbr_advance_gen(nbr) == 0); - UNIT_TEST_ASSERT(sixp_nbr_get_gen(nbr) == 0x09); - - UNIT_TEST_ASSERT(sixp_nbr_advance_gen(nbr) == 0); - UNIT_TEST_ASSERT(sixp_nbr_get_gen(nbr) == 0x01); - - UNIT_TEST_END(); -} - UNIT_TEST_REGISTER(test_next_seqno, "test next_seqno operation"); UNIT_TEST(test_next_seqno) @@ -189,7 +144,16 @@ UNIT_TEST(test_next_seqno) UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 14); UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0); UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 15); + + UNIT_TEST_ASSERT(sixp_nbr_set_next_seqno(nbr, 255) == 0); + UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 255); + + /* next_seqno must be 1 after 255. */ UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0); + UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 1); + + /* next_seqno is reset to 0 by sixp_nbr_reset_next_seqno() */ + UNIT_TEST_ASSERT(sixp_nbr_reset_next_seqno(nbr) == 0); UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 0); UNIT_TEST_END(); @@ -205,9 +169,6 @@ PROCESS_THREAD(test_process, ev, data) /* alloc / free */ UNIT_TEST_RUN(test_alloc_and_free); - /* GEN */ - UNIT_TEST_RUN(test_gen_management); - /* next sequence number */ UNIT_TEST_RUN(test_next_seqno); diff --git a/tests/16-6tisch/code/test-sixp-pkt.c b/tests/13-ieee802154/code-6tisch/test-sixp-pkt.c similarity index 83% rename from tests/16-6tisch/code/test-sixp-pkt.c rename to tests/13-ieee802154/code-6tisch/test-sixp-pkt.c index da73f71e8a4bda7d00d691f22ec29dce98555dd2..e49eed8405079a26da183572464aa10f3075091c 100644 --- a/tests/16-6tisch/code/test-sixp-pkt.c +++ b/tests/13-ieee802154/code-6tisch/test-sixp-pkt.c @@ -35,7 +35,7 @@ #include "contiki-lib.h" #include "lib/assert.h" -#include "net/mac/tsch/tsch-packet.h" +#include "net/mac/tsch/tsch.h" #include "net/mac/tsch/sixtop/sixp-pkt.h" #include "unit-test/unit-test.h" @@ -242,6 +242,45 @@ UNIT_TEST(test_set_get_metadata_list_req) UNIT_TEST_END(); } +UNIT_TEST_REGISTER(test_set_get_metadata_signal_req, + "test sixp_pkt_{set,get}_metadata(signal_req)"); +UNIT_TEST(test_set_get_metadata_signal_req) +{ + sixp_pkt_metadata_t testdata, result; + uint8_t *ptr = (uint8_t *)&testdata; + uint8_t *p_result = (uint8_t *)&result; + + ptr[0] = 0xAB; + ptr[1] = 0xCD; + + UNIT_TEST_BEGIN(); + + /* Signal Request */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(p_result[0] == 0x00); + UNIT_TEST_ASSERT(p_result[1] == 0x00); + UNIT_TEST_ASSERT( + sixp_pkt_set_metadata(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + testdata, + buf, sizeof(buf)) == 0); + ref_data[0] = 0xAB; + ref_data[1] = 0xCD; + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_get_metadata(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + &result, + buf, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(p_result[0] == 0xAB); + UNIT_TEST_ASSERT(p_result[1] == 0xCD); + + UNIT_TEST_END(); +} + UNIT_TEST_REGISTER(test_set_get_metadata_clear_req, "test sixp_pkt_{set,get}_metadata(clear_req)"); UNIT_TEST(test_set_get_metadata_clear_req) @@ -377,13 +416,13 @@ UNIT_TEST(test_set_get_metadata_error_res) UNIT_TEST_ASSERT(p_result[1] == 0x00); UNIT_TEST_ASSERT( sixp_pkt_set_metadata(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_get_metadata(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(p_result[0] == 0x00); @@ -414,13 +453,13 @@ UNIT_TEST(test_set_get_metadata_error_conf) UNIT_TEST_ASSERT(p_result[1] == 0x00); UNIT_TEST_ASSERT( sixp_pkt_set_metadata(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_get_metadata(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(p_result[0] == 0x00); @@ -589,6 +628,37 @@ UNIT_TEST(test_set_get_cell_options_list_req) UNIT_TEST_END(); } +UNIT_TEST_REGISTER(test_set_get_cell_options_signal_req, + "test sixp_pkt_{set,get}_cell_options(signal_req)"); +UNIT_TEST(test_set_get_cell_options_signal_req) +{ + sixp_pkt_cell_options_t testdata, result; + testdata = 0x07; + + UNIT_TEST_BEGIN(); + + /* Signal Request */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(result == 0x00); + UNIT_TEST_ASSERT( + sixp_pkt_set_cell_options(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + testdata, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_get_cell_options(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + &result, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(result == 0x00); + + UNIT_TEST_END(); +} + UNIT_TEST_REGISTER(test_set_get_cell_options_clear_req, "test sixp_pkt_{set,get}_cell_options(clear_req)"); UNIT_TEST(test_set_get_cell_options_clear_req) @@ -699,13 +769,13 @@ UNIT_TEST(test_set_get_cell_options_error_res) UNIT_TEST_ASSERT(result == 0x00); UNIT_TEST_ASSERT( sixp_pkt_set_cell_options(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_get_cell_options(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(result == 0x00); @@ -730,13 +800,13 @@ UNIT_TEST(test_set_get_cell_options_error_conf) UNIT_TEST_ASSERT(result == 0x00); UNIT_TEST_ASSERT( sixp_pkt_set_cell_options(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_get_cell_options(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(result == 0x00); @@ -902,6 +972,37 @@ UNIT_TEST(test_set_get_num_cells_list_req) UNIT_TEST_END(); } +UNIT_TEST_REGISTER(test_set_get_num_cells_signal_req, + "test sixp_pkt_{set,get}_num_cells(signal_req)"); +UNIT_TEST(test_set_get_num_cells_signal_req) +{ + sixp_pkt_num_cells_t testdata, result; + testdata = 0x07; + + UNIT_TEST_BEGIN(); + + /* Signal Request */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(result == 0x00); + UNIT_TEST_ASSERT( + sixp_pkt_set_num_cells(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + testdata, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_get_num_cells(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + &result, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(result == 0x00); + + UNIT_TEST_END(); +} + UNIT_TEST_REGISTER(test_set_get_num_cells_clear_req, "test sixp_pkt_{set,get}_num_cells(clear_req)"); UNIT_TEST(test_set_get_num_cells_clear_req) @@ -1011,13 +1112,13 @@ UNIT_TEST(test_set_get_num_cells_error_res) UNIT_TEST_ASSERT(result == 0x00); UNIT_TEST_ASSERT( sixp_pkt_set_num_cells(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_get_num_cells(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(result == 0x00); @@ -1042,13 +1143,13 @@ UNIT_TEST(test_set_get_num_cells_error_conf) UNIT_TEST_ASSERT(result == 0x00); UNIT_TEST_ASSERT( sixp_pkt_set_num_cells(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_get_num_cells(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, buf, sizeof(buf)) == -1); @@ -1211,6 +1312,37 @@ UNIT_TEST(test_set_get_reserved_list_req) UNIT_TEST_END(); } +UNIT_TEST_REGISTER(test_set_get_reserved_signal_req, + "test sixp_pkt_{set,get}_reserved(signal_req)"); +UNIT_TEST(test_set_get_reserved_signal_req) +{ + sixp_pkt_reserved_t testdata, result; + testdata = 0x07; + + UNIT_TEST_BEGIN(); + + /* Signal Request */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(result == 0x00); + UNIT_TEST_ASSERT( + sixp_pkt_set_reserved(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + testdata, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_get_reserved(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + &result, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(result == 0x00); + + UNIT_TEST_END(); +} + UNIT_TEST_REGISTER(test_set_get_reserved_clear_req, "test sixp_pkt_{set,get}_reserved(clear_req)"); UNIT_TEST(test_set_get_reserved_clear_req) @@ -1321,13 +1453,13 @@ UNIT_TEST(test_set_get_reserved_error_res) UNIT_TEST_ASSERT(result == 0x00); UNIT_TEST_ASSERT( sixp_pkt_set_reserved(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_get_reserved(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(result == 0x00); @@ -1352,13 +1484,13 @@ UNIT_TEST(test_set_get_reserved_error_conf) UNIT_TEST_ASSERT(result == 0x00); UNIT_TEST_ASSERT( sixp_pkt_set_reserved(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_get_reserved(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(result == 0x00); @@ -1523,6 +1655,37 @@ UNIT_TEST(test_set_get_offset_list_req) UNIT_TEST_END(); } +UNIT_TEST_REGISTER(test_set_get_offset_signal_req, + "test sixp_pkt_{set,get}_offset(signal_req)"); +UNIT_TEST(test_set_get_offset_signal_req) +{ + sixp_pkt_offset_t testdata, result; + testdata = 0xabcd; + + UNIT_TEST_BEGIN(); + + /* Signal Request */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(result == 0x00); + UNIT_TEST_ASSERT( + sixp_pkt_set_offset(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + testdata, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_get_offset(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + &result, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(result == 0x00); + + UNIT_TEST_END(); +} + UNIT_TEST_REGISTER(test_set_get_offset_clear_req, "test sixp_pkt_{set,get}_offset(clear_req)"); UNIT_TEST(test_set_get_offset_clear_req) @@ -1633,13 +1796,13 @@ UNIT_TEST(test_set_get_offset_error_res) UNIT_TEST_ASSERT(result == 0x00); UNIT_TEST_ASSERT( sixp_pkt_set_offset(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_get_offset(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(result == 0x00); @@ -1664,13 +1827,13 @@ UNIT_TEST(test_set_get_offset_error_conf) UNIT_TEST_ASSERT(result == 0x00); UNIT_TEST_ASSERT( sixp_pkt_set_offset(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_get_offset(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(result == 0x00); @@ -1836,6 +1999,37 @@ UNIT_TEST(test_set_get_max_num_cells_list_req) UNIT_TEST_END(); } +UNIT_TEST_REGISTER(test_set_get_max_num_cells_signal_req, + "test sixp_pkt_{set,get}_max_num_cells(signal_req)"); +UNIT_TEST(test_set_get_max_num_cells_signal_req) +{ + sixp_pkt_max_num_cells_t testdata, result; + testdata = 0x1234; + + UNIT_TEST_BEGIN(); + + /* Signal Request */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(result == 0x00); + UNIT_TEST_ASSERT( + sixp_pkt_set_max_num_cells(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + testdata, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_get_max_num_cells(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + &result, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(result == 0x00); + + UNIT_TEST_END(); +} + UNIT_TEST_REGISTER(test_set_get_max_num_cells_clear_req, "test sixp_pkt_{set,get}_max_num_cells(clear_req)"); UNIT_TEST(test_set_get_max_num_cells_clear_req) @@ -1946,13 +2140,13 @@ UNIT_TEST(test_set_get_max_num_cells_error_res) UNIT_TEST_ASSERT(result == 0x00); UNIT_TEST_ASSERT( sixp_pkt_set_max_num_cells(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_get_max_num_cells(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(result == 0x00); @@ -1977,13 +2171,13 @@ UNIT_TEST(test_set_get_max_num_cells_error_conf) UNIT_TEST_ASSERT(result == 0x00); UNIT_TEST_ASSERT( sixp_pkt_set_max_num_cells(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_get_max_num_cells(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(result == 0x00); @@ -2001,7 +2195,7 @@ UNIT_TEST(test_set_get_cell_list_add_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2048,7 +2242,7 @@ UNIT_TEST(test_set_get_cell_list_delete_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2095,7 +2289,7 @@ UNIT_TEST(test_set_get_cell_list_relocate_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2132,7 +2326,7 @@ UNIT_TEST(test_set_get_cell_list_count_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2169,7 +2363,7 @@ UNIT_TEST(test_set_get_cell_list_list_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2196,6 +2390,43 @@ UNIT_TEST(test_set_get_cell_list_list_req) UNIT_TEST_END(); } +UNIT_TEST_REGISTER(test_set_get_cell_list_signal_req, + "test sixp_pkt_{set,get}_cell_list(signal_req)"); +UNIT_TEST(test_set_get_cell_list_signal_req) +{ + /* make a cell list having four cells as test data */ + const uint8_t testdata[] = {0x01, 0x23, 0x45, 0x67, + 0x89, 0xab, 0xcd, 0xef, + 0xde, 0xad, 0xbe, 0xef, + 0xca, 0xfe, 0xca, 0xfe}; + const uint8_t *result; + sixp_pkt_offset_t result_len = 0; + + UNIT_TEST_BEGIN(); + + /* Signal Request */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(result == 0x00); + UNIT_TEST_ASSERT( + sixp_pkt_set_cell_list(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + testdata, sizeof(testdata), 0, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_get_cell_list(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + &result, &result_len, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(result_len == 0); + UNIT_TEST_ASSERT(memcmp(result, testdata, result_len) == 0); + + UNIT_TEST_END(); +} + UNIT_TEST_REGISTER(test_set_get_cell_list_clear_req, "test sixp_pkt_{set,get}_cell_list(clear_req)"); UNIT_TEST(test_set_get_cell_list_clear_req) @@ -2206,7 +2437,7 @@ UNIT_TEST(test_set_get_cell_list_clear_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2243,7 +2474,7 @@ UNIT_TEST(test_set_get_cell_list_success_res) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2281,7 +2512,7 @@ UNIT_TEST(test_set_get_cell_list_success_conf) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2319,7 +2550,7 @@ UNIT_TEST(test_set_get_cell_list_error_res) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2331,13 +2562,13 @@ UNIT_TEST(test_set_get_cell_list_error_res) UNIT_TEST_ASSERT(result == 0x00); UNIT_TEST_ASSERT( sixp_pkt_set_cell_list(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, sizeof(testdata), 0, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_get_cell_list(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, &result_len, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(result_len == 0); @@ -2356,7 +2587,7 @@ UNIT_TEST(test_set_get_cell_list_error_conf) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2368,13 +2599,13 @@ UNIT_TEST(test_set_get_cell_list_error_conf) UNIT_TEST_ASSERT(result == 0x00); UNIT_TEST_ASSERT( sixp_pkt_set_cell_list(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, sizeof(testdata), 0, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_get_cell_list(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, &result_len, buf, sizeof(testdata)) == -1); UNIT_TEST_ASSERT(result_len == 0); @@ -2393,7 +2624,7 @@ UNIT_TEST(test_set_get_rel_cell_list_add_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2436,7 +2667,7 @@ UNIT_TEST(test_set_get_rel_cell_list_delete_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2479,7 +2710,7 @@ UNIT_TEST(test_set_get_rel_cell_list_relocate_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2523,7 +2754,7 @@ UNIT_TEST(test_set_get_rel_cell_list_count_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2559,7 +2790,7 @@ UNIT_TEST(test_set_get_rel_cell_list_list_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2585,6 +2816,42 @@ UNIT_TEST(test_set_get_rel_cell_list_list_req) UNIT_TEST_END(); } +UNIT_TEST_REGISTER(test_set_get_rel_cell_list_signal_req, + "test sixp_pkt_{set,get}_rel_cell_list(signal_req)"); +UNIT_TEST(test_set_get_rel_cell_list_signal_req) +{ + /* make a cell list having four cells as test data */ + const uint8_t testdata[] = {0x01, 0x23, 0x45, 0x67, + 0x89, 0xab, 0xcd, 0xef, + 0xde, 0xad, 0xbe, 0xef, + 0xca, 0xfe, 0xca, 0xfe}; + const uint8_t *result; + sixp_pkt_offset_t result_len = 0; + + UNIT_TEST_BEGIN(); + + /* Signal Request */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_set_rel_cell_list(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + testdata, sizeof(testdata), 0, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + result = NULL; + UNIT_TEST_ASSERT( + sixp_pkt_get_rel_cell_list(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + &result, &result_len, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(result == NULL); + UNIT_TEST_ASSERT(result_len == 0); + + UNIT_TEST_END(); +} + UNIT_TEST_REGISTER(test_set_get_rel_cell_list_clear_req, "test sixp_pkt_{set,get}_rel_cell_list(clear_req)"); UNIT_TEST(test_set_get_rel_cell_list_clear_req) @@ -2595,7 +2862,7 @@ UNIT_TEST(test_set_get_rel_cell_list_clear_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2632,7 +2899,7 @@ UNIT_TEST(test_set_get_rel_cell_list_success_res) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2669,7 +2936,7 @@ UNIT_TEST(test_set_get_rel_cell_list_success_conf) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2706,7 +2973,7 @@ UNIT_TEST(test_set_get_rel_cell_list_error_res) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2716,7 +2983,7 @@ UNIT_TEST(test_set_get_rel_cell_list_error_res) UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_set_rel_cell_list(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, sizeof(testdata), 0, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); @@ -2724,7 +2991,7 @@ UNIT_TEST(test_set_get_rel_cell_list_error_res) result = NULL; UNIT_TEST_ASSERT( sixp_pkt_get_rel_cell_list(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, &result_len, buf, sizeof(testdata)) == -1); UNIT_TEST_ASSERT(result == NULL); @@ -2743,7 +3010,7 @@ UNIT_TEST(test_set_get_rel_cell_list_error_conf) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2753,14 +3020,14 @@ UNIT_TEST(test_set_get_rel_cell_list_error_conf) UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_set_rel_cell_list(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, sizeof(testdata), 0, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); result = NULL; UNIT_TEST_ASSERT( sixp_pkt_get_rel_cell_list(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, &result_len, buf, sizeof(testdata)) == -1); UNIT_TEST_ASSERT(result == NULL); @@ -2779,7 +3046,7 @@ UNIT_TEST(test_set_get_cand_cell_list_add_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2822,7 +3089,7 @@ UNIT_TEST(test_set_get_cand_cell_list_delete_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2865,7 +3132,7 @@ UNIT_TEST(test_set_get_cand_cell_list_relocate_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2909,7 +3176,7 @@ UNIT_TEST(test_set_get_cand_cell_list_count_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2945,7 +3212,7 @@ UNIT_TEST(test_set_get_cand_cell_list_list_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -2971,6 +3238,42 @@ UNIT_TEST(test_set_get_cand_cell_list_list_req) UNIT_TEST_END(); } +UNIT_TEST_REGISTER(test_set_get_cand_cell_list_signal_req, + "test sixp_pkt_{set,get}_cand_cell_list(signal_req)"); +UNIT_TEST(test_set_get_cand_cell_list_signal_req) +{ + /* make a cell list having four cells as test data */ + const uint8_t testdata[] = {0x01, 0x23, 0x45, 0x67, + 0x89, 0xab, 0xcd, 0xef, + 0xde, 0xad, 0xbe, 0xef, + 0xca, 0xfe, 0xca, 0xfe}; + const uint8_t *result; + sixp_pkt_offset_t result_len = 0; + + UNIT_TEST_BEGIN(); + + /* Signal Request */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_set_cand_cell_list(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + testdata, sizeof(testdata), 0, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + result = NULL; + UNIT_TEST_ASSERT( + sixp_pkt_get_cand_cell_list(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + &result, &result_len, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(result == NULL); + UNIT_TEST_ASSERT(result_len == 0); + + UNIT_TEST_END(); +} + UNIT_TEST_REGISTER(test_set_get_cand_cell_list_clear_req, "test sixp_pkt_{set,get}_cand_cell_list(clear_req)"); UNIT_TEST(test_set_get_cand_cell_list_clear_req) @@ -2981,7 +3284,7 @@ UNIT_TEST(test_set_get_cand_cell_list_clear_req) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -3018,7 +3321,7 @@ UNIT_TEST(test_set_get_cand_cell_list_success_res) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -3055,7 +3358,7 @@ UNIT_TEST(test_set_get_cand_cell_list_success_conf) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -3092,7 +3395,7 @@ UNIT_TEST(test_set_get_cand_cell_list_error_res) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -3102,7 +3405,7 @@ UNIT_TEST(test_set_get_cand_cell_list_error_res) UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_set_cand_cell_list(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, sizeof(testdata), 0, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); @@ -3110,7 +3413,7 @@ UNIT_TEST(test_set_get_cand_cell_list_error_res) result = NULL; UNIT_TEST_ASSERT( sixp_pkt_get_cand_cell_list(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, &result_len, buf, sizeof(testdata)) == -1); UNIT_TEST_ASSERT(result == NULL); @@ -3129,7 +3432,7 @@ UNIT_TEST(test_set_get_cand_cell_list_error_conf) 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xca, 0xfe}; const uint8_t *result; - sixp_pkt_offset_t result_len; + sixp_pkt_offset_t result_len = 0; UNIT_TEST_BEGIN(); @@ -3139,14 +3442,14 @@ UNIT_TEST(test_set_get_cand_cell_list_error_conf) UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_set_cand_cell_list(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, sizeof(testdata), 0, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); result = NULL; UNIT_TEST_ASSERT( sixp_pkt_get_cand_cell_list(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, &result_len, buf, sizeof(testdata)) == -1); UNIT_TEST_ASSERT(result == NULL); @@ -3165,8 +3468,7 @@ UNIT_TEST(test_parse_valid_version) * - Reserved (2-bit): 0 * - Code (8-bit) : 2 (delete) * - SFID (8-bit) : 0xfe - * - SeqNum (4-bit) : 10 - * - GEN (4-bit) : 6 + * - SeqNum (8-bit) : 0x6a * - Other Field : (4-octet payload) */ const uint8_t test_buf[] = {0x00, 0x02, 0xfe, 0x6a, @@ -3179,8 +3481,7 @@ UNIT_TEST(test_parse_valid_version) UNIT_TEST_ASSERT(pkt.type == SIXP_PKT_TYPE_REQUEST); UNIT_TEST_ASSERT(pkt.code.cmd == SIXP_PKT_CMD_DELETE); UNIT_TEST_ASSERT(pkt.sfid == 0xfe); - UNIT_TEST_ASSERT(pkt.seqno == 10); - UNIT_TEST_ASSERT(pkt.gen == 6); + UNIT_TEST_ASSERT(pkt.seqno == 0x6a); UNIT_TEST_ASSERT(pkt.body == &test_buf[4]); UNIT_TEST_ASSERT(pkt.body_len == 4); @@ -3197,8 +3498,7 @@ UNIT_TEST(test_parse_invalid_version) * - Reserved (2-bit): 0 * - Code (8-bit) : 2 (delete) * - SFID (8-bit) : 0xfe - * - SeqNum (4-bit) : 10 - * - GEN (4-bit) : 6 + * - SeqNum (8-bit) : 0x6a * - Other Field : (4-octet payload) */ const uint8_t test_buf[] = {0x02, 0x08, 0xfe, 0x6a, @@ -3243,8 +3543,7 @@ UNIT_TEST(test_parse_invalid_cmd) * - Reserved (2-bit): 0 * - Code (8-bit) : 10 (undefined) * - SFID (8-bit) : 0xfe - * - SeqNum (4-bit) : 10 - * - GEN (4-bit) : 6 + * - SeqNum (8-bit) : 0x6a * - Other Field : (4-octet payload) */ const uint8_t test_buf[] = {0x01, 0x0a, 0xfe, 0x6a, @@ -3268,8 +3567,7 @@ UNIT_TEST(test_parse_invalid_rc) * - Reserved (2-bit): 0 * - Code (8-bit) : 15 (undefined) * - SFID (8-bit) : 0xfe - * - SeqNum (4-bit) : 10 - * - GEN (4-bit) : 6 + * - SeqNum (8-bit) : 0x6a * - Other Field : (4-octet payload) */ const uint8_t test_buf[] = {0x11, 0x0f, 0xfe, 0x6a}; @@ -3292,8 +3590,7 @@ UNIT_TEST(test_parse_invalid_type) * - Reserved (2-bit): 0 * - Code (8-bit) : 0 (undefined) * - SFID (8-bit) : 0xfe - * - SeqNum (4-bit) : 10 - * - GEN (4-bit) : 6 + * - SeqNum (8-bit) : 0x6a * - Other Field : (4-octet payload) */ const uint8_t test_buf[] = {0x31, 0x00, 0xfe, 0x6a}; @@ -3316,8 +3613,7 @@ UNIT_TEST(test_create_valid_packet) * - Reserved (2-bit): 0 * - Code (8-bit) : 2 (delete) * - SFID (8-bit) : 0xfe - * - SeqNum (4-bit) : 10 - * - GEN (4-bit) : 6 + * - SeqNum (8-bit) : 0x6a * - Other Field : (4-octet payload) */ const uint8_t test_body[] = {0xde, 0xad, 0xbe, 0xef}; @@ -3331,7 +3627,7 @@ UNIT_TEST(test_create_valid_packet) UNIT_TEST_ASSERT( sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_DELETE, - 0xfe, 10, 6, + 0xfe, 0x6a, test_body, sizeof(test_body), &pkt) == 0); hdr_ptr = packetbuf_hdrptr(); @@ -3356,8 +3652,7 @@ UNIT_TEST(test_create_valid_packet) UNIT_TEST_ASSERT(pkt.type == SIXP_PKT_TYPE_REQUEST); UNIT_TEST_ASSERT(pkt.code.cmd == SIXP_PKT_CMD_DELETE); UNIT_TEST_ASSERT(pkt.sfid == 0xfe); - UNIT_TEST_ASSERT(pkt.seqno == 10); - UNIT_TEST_ASSERT(pkt.gen == 6); + UNIT_TEST_ASSERT(pkt.seqno == 0x6a); UNIT_TEST_ASSERT(memcmp(pkt.body, test_body, pkt.body_len) == 0); UNIT_TEST_ASSERT(pkt.body_len == 4); @@ -3374,8 +3669,7 @@ UNIT_TEST(test_create_valid_packet_with_null_pkt) * - Reserved (2-bit): 0 * - Code (8-bit) : 2 (delete) * - SFID (8-bit) : 0xfe - * - SeqNum (4-bit) : 10 - * - GEN (4-bit) : 6 + * - SeqNum (8-bit) : 0x6a * - Other Field : (4-octet payload) */ const uint8_t test_body[] = {0xde, 0xad, 0xbe, 0xef}; @@ -3387,7 +3681,7 @@ UNIT_TEST(test_create_valid_packet_with_null_pkt) UNIT_TEST_ASSERT( sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_DELETE, - 0xfe, 10, 6, + 0xfe, 0x6a, test_body, sizeof(test_body), NULL) == 0); hdr_ptr = packetbuf_hdrptr(); @@ -3423,8 +3717,7 @@ UNIT_TEST(test_create_too_long_body) * - Reserved (2-bit): 0 * - Code (8-bit) : 2 (delete) * - SFID (8-bit) : 0xfe - * - SeqNum (4-bit) : 10 - * - GEN (4-bit) : 6 + * - SeqNum (8-bit) : 0x6a * - Other Field : (4-octet payload) */ const uint8_t test_body[PACKETBUF_SIZE + 1]; @@ -3435,7 +3728,7 @@ UNIT_TEST(test_create_too_long_body) UNIT_TEST_ASSERT( sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_DELETE, - 0xfe, 10, 6, + 0xfe, 0x6a, test_body, sizeof(test_body), NULL) == -1); UNIT_TEST_ASSERT(packetbuf_hdrlen() == 0); UNIT_TEST_ASSERT(packetbuf_datalen() == 0); @@ -3598,22 +3891,22 @@ UNIT_TEST(test_set_get_total_num_cells_list_req) UNIT_TEST_END(); } -UNIT_TEST_REGISTER(test_set_get_total_num_cells_clear_req, - "test sixp_pkt_{set,get}_total_num_cells(clear_req)"); -UNIT_TEST(test_set_get_total_num_cells_clear_req) +UNIT_TEST_REGISTER(test_set_get_total_num_cells_signal_req, + "test sixp_pkt_{set,get}_total_num_cells(signal_req)"); +UNIT_TEST(test_set_get_total_num_cells_signal_req) { sixp_pkt_total_num_cells_t testdata, result; testdata = 0xcafe; UNIT_TEST_BEGIN(); - /* Clear Request */ + /* Signal Request */ memset(buf, 0, sizeof(buf)); memset(ref_data, 0, sizeof(ref_data)); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_set_total_num_cells(SIXP_PKT_TYPE_REQUEST, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_CLEAR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, testdata, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); @@ -3621,7 +3914,7 @@ UNIT_TEST(test_set_get_total_num_cells_clear_req) result = 0; UNIT_TEST_ASSERT( sixp_pkt_get_total_num_cells(SIXP_PKT_TYPE_REQUEST, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_CLEAR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, &result, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(result == 0); @@ -3629,10 +3922,41 @@ UNIT_TEST(test_set_get_total_num_cells_clear_req) UNIT_TEST_END(); } -UNIT_TEST_REGISTER(test_set_get_total_num_cells_success_res, - "test sixp_pkt_{set,get}_total_num_cells(success_res)"); -UNIT_TEST(test_set_get_total_num_cells_success_res) -{ +UNIT_TEST_REGISTER(test_set_get_total_num_cells_clear_req, + "test sixp_pkt_{set,get}_total_num_cells(clear_req)"); +UNIT_TEST(test_set_get_total_num_cells_clear_req) +{ + sixp_pkt_total_num_cells_t testdata, result; + testdata = 0xcafe; + + UNIT_TEST_BEGIN(); + + /* Clear Request */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_set_total_num_cells(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_CLEAR, + testdata, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + + result = 0; + UNIT_TEST_ASSERT( + sixp_pkt_get_total_num_cells(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_CLEAR, + &result, + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(result == 0); + + UNIT_TEST_END(); +} + +UNIT_TEST_REGISTER(test_set_get_total_num_cells_success_res, + "test sixp_pkt_{set,get}_total_num_cells(success_res)"); +UNIT_TEST(test_set_get_total_num_cells_success_res) +{ sixp_pkt_total_num_cells_t testdata, result; testdata = 0xcafe; @@ -3710,7 +4034,7 @@ UNIT_TEST(test_set_get_total_num_cells_error_res) UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_set_total_num_cells(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); @@ -3718,7 +4042,7 @@ UNIT_TEST(test_set_get_total_num_cells_error_res) result = 0; UNIT_TEST_ASSERT( sixp_pkt_get_total_num_cells(SIXP_PKT_TYPE_RESPONSE, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(result == 0); @@ -3741,7 +4065,7 @@ UNIT_TEST(test_set_get_total_num_cells_error_conf) UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); UNIT_TEST_ASSERT( sixp_pkt_set_total_num_cells(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, testdata, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); @@ -3749,7 +4073,7 @@ UNIT_TEST(test_set_get_total_num_cells_error_conf) result = 0; UNIT_TEST_ASSERT( sixp_pkt_get_total_num_cells(SIXP_PKT_TYPE_CONFIRMATION, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERROR, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, &result, buf, sizeof(buf)) == -1); UNIT_TEST_ASSERT(result == 0); @@ -3757,6 +4081,393 @@ UNIT_TEST(test_set_get_total_num_cells_error_conf) UNIT_TEST_END(); } +UNIT_TEST_REGISTER(test_set_get_payload_add_req, + "test sixp_pkt_{set,get}_payload(add_req)"); +UNIT_TEST(test_set_get_payload_add_req) +{ + uint8_t testdata[2], result[2]; + uint8_t *ptr = (uint8_t *)&testdata; + uint8_t *p_result = (uint8_t *)&result; + + ptr[0] = 0xAB; + ptr[1] = 0xCD; + + UNIT_TEST_BEGIN(); + + /* Add Request */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(p_result[0] == 0x00); + UNIT_TEST_ASSERT(p_result[1] == 0x00); + UNIT_TEST_ASSERT( + sixp_pkt_set_payload(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD, + testdata, sizeof(testdata), + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_get_payload(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD, + result, sizeof(result), + buf, sizeof(buf)) == -1); + + UNIT_TEST_END(); +} + +UNIT_TEST_REGISTER(test_set_get_payload_delete_req, + "test sixp_pkt_{set,get}_payload(delete_req)"); +UNIT_TEST(test_set_get_payload_delete_req) +{ + uint8_t testdata[2], result[2]; + uint8_t *ptr = (uint8_t *)&testdata; + uint8_t *p_result = (uint8_t *)&result; + + ptr[0] = 0xAB; + ptr[1] = 0xCD; + + UNIT_TEST_BEGIN(); + + /* Delete Request */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(p_result[0] == 0x00); + UNIT_TEST_ASSERT(p_result[1] == 0x00); + UNIT_TEST_ASSERT( + sixp_pkt_set_payload(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_DELETE, + testdata, sizeof(testdata), + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_get_payload(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_DELETE, + result, sizeof(result), + buf, sizeof(buf)) == -1); + + UNIT_TEST_END(); +} + +UNIT_TEST_REGISTER(test_set_get_payload_relocate_req, + "test sixp_pkt_{set,get}_payload(relocate_req)"); +UNIT_TEST(test_set_get_payload_relocate_req) +{ + uint8_t testdata[2], result[2]; + uint8_t *ptr = (uint8_t *)&testdata; + uint8_t *p_result = (uint8_t *)&result; + + ptr[0] = 0xAB; + ptr[1] = 0xCD; + + UNIT_TEST_BEGIN(); + + /* Relocate Request */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(p_result[0] == 0x00); + UNIT_TEST_ASSERT(p_result[1] == 0x00); + UNIT_TEST_ASSERT( + sixp_pkt_set_payload(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_RELOCATE, + testdata, sizeof(testdata), + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_get_payload(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_RELOCATE, + result, sizeof(result), + buf, sizeof(buf)) == -1); + + UNIT_TEST_END(); +} + +UNIT_TEST_REGISTER(test_set_get_payload_count_req, + "test sixp_pkt_{set,get}_payload(count_req)"); +UNIT_TEST(test_set_get_payload_count_req) +{ + uint8_t testdata[2], result[2]; + uint8_t *ptr = (uint8_t *)&testdata; + uint8_t *p_result = (uint8_t *)&result; + + ptr[0] = 0xAB; + ptr[1] = 0xCD; + + UNIT_TEST_BEGIN(); + + /* Count Request */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(p_result[0] == 0x00); + UNIT_TEST_ASSERT(p_result[1] == 0x00); + UNIT_TEST_ASSERT( + sixp_pkt_set_payload(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_COUNT, + testdata, sizeof(testdata), + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_get_payload(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_COUNT, + result, sizeof(result), + buf, sizeof(buf)) == -1); + + UNIT_TEST_END(); +} + +UNIT_TEST_REGISTER(test_set_get_payload_list_req, + "test sixp_pkt_{set,get}_payload(list_req)"); +UNIT_TEST(test_set_get_payload_list_req) +{ + uint8_t testdata[2], result[2]; + uint8_t *ptr = (uint8_t *)&testdata; + + ptr[0] = 0xAB; + ptr[1] = 0xCD; + + UNIT_TEST_BEGIN(); + + /* List Request */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_set_payload(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_LIST, + testdata, sizeof(testdata), + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_get_payload(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_LIST, + result, sizeof(result), + buf, sizeof(buf)) == -1); + + UNIT_TEST_END(); +} + +UNIT_TEST_REGISTER(test_set_get_payload_signal_req, + "test sixp_pkt_{set,get}_payload(signal_req)"); +UNIT_TEST(test_set_get_payload_signal_req) +{ + uint8_t testdata[2], result[2]; + uint8_t *ptr = (uint8_t *)&testdata; + uint8_t *p_result = (uint8_t *)&result; + + ptr[0] = 0xAB; + ptr[1] = 0xCD; + + UNIT_TEST_BEGIN(); + + /* Signal Request */ + memset(buf, 0, sizeof(buf)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(p_result[0] == 0x00); + UNIT_TEST_ASSERT(p_result[1] == 0x00); + UNIT_TEST_ASSERT( + sixp_pkt_set_payload(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + testdata, sizeof(testdata), + buf, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(buf[2] == 0xAB); + UNIT_TEST_ASSERT(buf[3] == 0xCD); + UNIT_TEST_ASSERT( + sixp_pkt_get_payload(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_SIGNAL, + result, sizeof(result), + buf, sizeof(sixp_pkt_metadata_t) + 2) == 0); + UNIT_TEST_ASSERT(p_result[0] == 0xAB); + UNIT_TEST_ASSERT(p_result[1] == 0xCD); + + UNIT_TEST_END(); +} + +UNIT_TEST_REGISTER(test_set_get_payload_clear_req, + "test sixp_pkt_{set,get}_payload(clear_req)"); +UNIT_TEST(test_set_get_payload_clear_req) +{ + uint8_t testdata[2], result[2]; + uint8_t *ptr = (uint8_t *)&testdata; + uint8_t *p_result = (uint8_t *)&result; + + ptr[0] = 0xAB; + ptr[1] = 0xCD; + + UNIT_TEST_BEGIN(); + + /* Clear Request */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(p_result[0] == 0x00); + UNIT_TEST_ASSERT(p_result[1] == 0x00); + UNIT_TEST_ASSERT( + sixp_pkt_set_payload(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_CLEAR, + testdata, sizeof(testdata), + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_get_payload(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_CLEAR, + result, sizeof(result), + buf, sizeof(buf)) == -1); + + UNIT_TEST_END(); +} + +UNIT_TEST_REGISTER(test_set_get_payload_success_res, + "test sixp_pkt_{set,get}_payload(success_res)"); +UNIT_TEST(test_set_get_payload_success_res) +{ + uint8_t testdata[2], result[2]; + uint8_t *ptr = (uint8_t *)&testdata; + uint8_t *p_result = (uint8_t *)&result; + + ptr[0] = 0xAB; + ptr[1] = 0xCD; + + UNIT_TEST_BEGIN(); + + /* Success Response */ + memset(buf, 0, sizeof(buf)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(p_result[0] == 0x00); + UNIT_TEST_ASSERT(p_result[1] == 0x00); + UNIT_TEST_ASSERT( + sixp_pkt_set_payload(SIXP_PKT_TYPE_RESPONSE, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS, + testdata, sizeof(testdata), + buf, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(buf[0] == 0xAB); + UNIT_TEST_ASSERT(buf[1] == 0xCD); + UNIT_TEST_ASSERT( + sixp_pkt_get_payload(SIXP_PKT_TYPE_RESPONSE, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS, + result, sizeof(result), + buf, 2) == 0); + UNIT_TEST_ASSERT(p_result[0] == 0xAB); + UNIT_TEST_ASSERT(p_result[1] == 0xCD); + + UNIT_TEST_END(); +} + +UNIT_TEST_REGISTER(test_set_get_payload_success_conf, + "test sixp_pkt_{set,get}_payload(success_conf)"); +UNIT_TEST(test_set_get_payload_success_conf) +{ + uint8_t testdata[2], result[2]; + uint8_t *ptr = (uint8_t *)&testdata; + uint8_t *p_result = (uint8_t *)&result; + + ptr[0] = 0xAB; + ptr[1] = 0xCD; + + UNIT_TEST_BEGIN(); + + /* Success Confirmation */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(p_result[0] == 0x00); + UNIT_TEST_ASSERT(p_result[1] == 0x00); + UNIT_TEST_ASSERT( + sixp_pkt_set_payload(SIXP_PKT_TYPE_CONFIRMATION, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS, + testdata, sizeof(testdata), + buf, sizeof(buf)) == 0); + ref_data[2] = 0xAB; + ref_data[3] = 0xCD; + UNIT_TEST_ASSERT( + sixp_pkt_get_payload(SIXP_PKT_TYPE_CONFIRMATION, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS, + result, sizeof(result), + buf, 2) == 0); + UNIT_TEST_ASSERT(p_result[0] == 0xAB); + UNIT_TEST_ASSERT(p_result[1] == 0xCD); + + UNIT_TEST_END(); +} + +UNIT_TEST_REGISTER(test_set_get_payload_error_res, + "test sixp_pkt_{set,get}_payload(err_res)"); +UNIT_TEST(test_set_get_payload_error_res) +{ + uint8_t testdata[2], result[2]; + uint8_t *ptr = (uint8_t *)&testdata; + uint8_t *p_result = (uint8_t *)&result; + + ptr[0] = 0xAB; + ptr[1] = 0xCD; + + UNIT_TEST_BEGIN(); + + /* Error Response */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(p_result[0] == 0x00); + UNIT_TEST_ASSERT(p_result[1] == 0x00); + UNIT_TEST_ASSERT( + sixp_pkt_set_payload(SIXP_PKT_TYPE_RESPONSE, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, + testdata, sizeof(testdata), + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_get_payload(SIXP_PKT_TYPE_RESPONSE, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, + result, sizeof(result), + buf, sizeof(buf)) == -1); + + UNIT_TEST_END(); +} + +UNIT_TEST_REGISTER(test_set_get_payload_error_conf, + "test sixp_pkt_{set,get}_payload(err_conf)"); +UNIT_TEST(test_set_get_payload_error_conf) +{ + uint8_t testdata[2], result[2]; + uint8_t *ptr = (uint8_t *)&testdata; + uint8_t *p_result = (uint8_t *)&result; + + ptr[0] = 0xAB; + ptr[1] = 0xCD; + + UNIT_TEST_BEGIN(); + + /* Error Confirmation */ + memset(buf, 0, sizeof(buf)); + memset(ref_data, 0, sizeof(ref_data)); + memset(&result, 0, sizeof(result)); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT(p_result[0] == 0x00); + UNIT_TEST_ASSERT(p_result[1] == 0x00); + UNIT_TEST_ASSERT( + sixp_pkt_set_payload(SIXP_PKT_TYPE_CONFIRMATION, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, + testdata, sizeof(testdata), + buf, sizeof(buf)) == -1); + UNIT_TEST_ASSERT(memcmp(buf, ref_data, sizeof(buf)) == 0); + UNIT_TEST_ASSERT( + sixp_pkt_get_payload(SIXP_PKT_TYPE_CONFIRMATION, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR, + result, sizeof(result), + buf, sizeof(buf)) == -1); + + UNIT_TEST_END(); +} + PROCESS_THREAD(test_process, ev, data) { PROCESS_BEGIN(); @@ -3771,6 +4482,7 @@ PROCESS_THREAD(test_process, ev, data) UNIT_TEST_RUN(test_set_get_metadata_relocate_req); UNIT_TEST_RUN(test_set_get_metadata_count_req); UNIT_TEST_RUN(test_set_get_metadata_list_req); + UNIT_TEST_RUN(test_set_get_metadata_signal_req); UNIT_TEST_RUN(test_set_get_metadata_clear_req); UNIT_TEST_RUN(test_set_get_metadata_success_res); UNIT_TEST_RUN(test_set_get_metadata_success_conf); @@ -3783,6 +4495,7 @@ PROCESS_THREAD(test_process, ev, data) UNIT_TEST_RUN(test_set_get_cell_options_relocate_req); UNIT_TEST_RUN(test_set_get_cell_options_count_req); UNIT_TEST_RUN(test_set_get_cell_options_list_req); + UNIT_TEST_RUN(test_set_get_cell_options_signal_req); UNIT_TEST_RUN(test_set_get_cell_options_clear_req); UNIT_TEST_RUN(test_set_get_cell_options_success_res); UNIT_TEST_RUN(test_set_get_cell_options_success_conf); @@ -3795,6 +4508,7 @@ PROCESS_THREAD(test_process, ev, data) UNIT_TEST_RUN(test_set_get_num_cells_relocate_req); UNIT_TEST_RUN(test_set_get_num_cells_count_req); UNIT_TEST_RUN(test_set_get_num_cells_list_req); + UNIT_TEST_RUN(test_set_get_num_cells_signal_req); UNIT_TEST_RUN(test_set_get_num_cells_clear_req); UNIT_TEST_RUN(test_set_get_num_cells_success_res); UNIT_TEST_RUN(test_set_get_num_cells_success_conf); @@ -3807,6 +4521,7 @@ PROCESS_THREAD(test_process, ev, data) UNIT_TEST_RUN(test_set_get_reserved_relocate_req); UNIT_TEST_RUN(test_set_get_reserved_count_req); UNIT_TEST_RUN(test_set_get_reserved_list_req); + UNIT_TEST_RUN(test_set_get_reserved_signal_req); UNIT_TEST_RUN(test_set_get_reserved_clear_req); UNIT_TEST_RUN(test_set_get_reserved_success_res); UNIT_TEST_RUN(test_set_get_reserved_success_conf); @@ -3819,6 +4534,7 @@ PROCESS_THREAD(test_process, ev, data) UNIT_TEST_RUN(test_set_get_offset_relocate_req); UNIT_TEST_RUN(test_set_get_offset_count_req); UNIT_TEST_RUN(test_set_get_offset_list_req); + UNIT_TEST_RUN(test_set_get_offset_signal_req); UNIT_TEST_RUN(test_set_get_offset_clear_req); UNIT_TEST_RUN(test_set_get_offset_success_res); UNIT_TEST_RUN(test_set_get_offset_success_conf); @@ -3831,6 +4547,7 @@ PROCESS_THREAD(test_process, ev, data) UNIT_TEST_RUN(test_set_get_max_num_cells_relocate_req); UNIT_TEST_RUN(test_set_get_max_num_cells_count_req); UNIT_TEST_RUN(test_set_get_max_num_cells_list_req); + UNIT_TEST_RUN(test_set_get_max_num_cells_signal_req); UNIT_TEST_RUN(test_set_get_max_num_cells_clear_req); UNIT_TEST_RUN(test_set_get_max_num_cells_success_res); UNIT_TEST_RUN(test_set_get_max_num_cells_success_conf); @@ -3843,6 +4560,7 @@ PROCESS_THREAD(test_process, ev, data) UNIT_TEST_RUN(test_set_get_cell_list_relocate_req); UNIT_TEST_RUN(test_set_get_cell_list_count_req); UNIT_TEST_RUN(test_set_get_cell_list_list_req); + UNIT_TEST_RUN(test_set_get_cell_list_signal_req); UNIT_TEST_RUN(test_set_get_cell_list_clear_req); UNIT_TEST_RUN(test_set_get_cell_list_success_res); UNIT_TEST_RUN(test_set_get_cell_list_success_conf); @@ -3855,6 +4573,7 @@ PROCESS_THREAD(test_process, ev, data) UNIT_TEST_RUN(test_set_get_rel_cell_list_relocate_req); UNIT_TEST_RUN(test_set_get_rel_cell_list_count_req); UNIT_TEST_RUN(test_set_get_rel_cell_list_list_req); + UNIT_TEST_RUN(test_set_get_rel_cell_list_signal_req); UNIT_TEST_RUN(test_set_get_rel_cell_list_clear_req); UNIT_TEST_RUN(test_set_get_rel_cell_list_success_res); UNIT_TEST_RUN(test_set_get_rel_cell_list_success_conf); @@ -3867,6 +4586,7 @@ PROCESS_THREAD(test_process, ev, data) UNIT_TEST_RUN(test_set_get_cand_cell_list_relocate_req); UNIT_TEST_RUN(test_set_get_cand_cell_list_count_req); UNIT_TEST_RUN(test_set_get_cand_cell_list_list_req); + UNIT_TEST_RUN(test_set_get_cand_cell_list_signal_req); UNIT_TEST_RUN(test_set_get_cand_cell_list_clear_req); UNIT_TEST_RUN(test_set_get_cand_cell_list_success_res); UNIT_TEST_RUN(test_set_get_cand_cell_list_success_conf); @@ -3879,12 +4599,26 @@ PROCESS_THREAD(test_process, ev, data) UNIT_TEST_RUN(test_set_get_total_num_cells_relocate_req); UNIT_TEST_RUN(test_set_get_total_num_cells_count_req); UNIT_TEST_RUN(test_set_get_total_num_cells_list_req); + UNIT_TEST_RUN(test_set_get_total_num_cells_signal_req); UNIT_TEST_RUN(test_set_get_total_num_cells_clear_req); UNIT_TEST_RUN(test_set_get_total_num_cells_success_res); UNIT_TEST_RUN(test_set_get_total_num_cells_success_conf); UNIT_TEST_RUN(test_set_get_total_num_cells_error_res); UNIT_TEST_RUN(test_set_get_total_num_cells_error_conf); + /* payload */ + UNIT_TEST_RUN(test_set_get_payload_add_req); + UNIT_TEST_RUN(test_set_get_payload_delete_req); + UNIT_TEST_RUN(test_set_get_payload_relocate_req); + UNIT_TEST_RUN(test_set_get_payload_count_req); + UNIT_TEST_RUN(test_set_get_payload_list_req); + UNIT_TEST_RUN(test_set_get_payload_signal_req); + UNIT_TEST_RUN(test_set_get_payload_clear_req); + UNIT_TEST_RUN(test_set_get_payload_success_res); + UNIT_TEST_RUN(test_set_get_payload_success_conf); + UNIT_TEST_RUN(test_set_get_payload_error_res); + UNIT_TEST_RUN(test_set_get_payload_error_conf); + /* parse */ UNIT_TEST_RUN(test_parse_valid_version); UNIT_TEST_RUN(test_parse_invalid_version); diff --git a/tests/16-6tisch/code/test-sixp-trans.c b/tests/13-ieee802154/code-6tisch/test-sixp-trans.c similarity index 92% rename from tests/16-6tisch/code/test-sixp-trans.c rename to tests/13-ieee802154/code-6tisch/test-sixp-trans.c index 169d425b3e3c87a8e48bced66107fe6aece6b280..76afd3b7e3a23c38dcb0bb910af551f4588ad9bf 100644 --- a/tests/16-6tisch/code/test-sixp-trans.c +++ b/tests/13-ieee802154/code-6tisch/test-sixp-trans.c @@ -35,8 +35,10 @@ #include "contiki-lib.h" #include "lib/assert.h" +#include "net/packetbuf.h" #include "net/mac/tsch/tsch.h" #include "net/mac/tsch/sixtop/sixtop.h" +#include "net/mac/tsch/sixtop/sixp-nbr.h" #include "net/mac/tsch/sixtop/sixp-trans.h" #include "unit-test/unit-test.h" @@ -1075,6 +1077,84 @@ UNIT_TEST(test_state_transition_invalid_transition_responder) UNIT_TEST_END(); } +UNIT_TEST_REGISTER(test_next_seqno_increment_on_request_sent, + "test next_seqno is incremented on request_sent"); +UNIT_TEST(test_next_seqno_increment_on_request_sent) +{ + linkaddr_t peer_addr; + sixp_nbr_t *nbr; + sixp_trans_t *trans; + + UNIT_TEST_BEGIN(); + + test_setup(); + + peer_addr.u8[0] = 1; + + UNIT_TEST_ASSERT((nbr = sixp_nbr_alloc(&peer_addr)) != NULL); + UNIT_TEST_ASSERT(sixp_nbr_set_next_seqno(nbr, 10) == 0); + UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 10); + + UNIT_TEST_ASSERT(sixp_output(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD, + TEST_SF_SFID, NULL, 0, &peer_addr, + NULL, NULL, 0) == 0); + /* next_seqno must not be changed by sixp_output() */ + UNIT_TEST_ASSERT((trans = sixp_trans_find(&peer_addr)) != NULL); + UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 10); + UNIT_TEST_ASSERT(sixp_trans_transit_state(trans, + SIXP_TRANS_STATE_REQUEST_SENT) + == 0); + UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 11); + + UNIT_TEST_END(); +} + +UNIT_TEST_REGISTER(test_next_seqno_increment_on_response_sent, + "test next_seqno is incremented on response_sent"); +UNIT_TEST(test_next_seqno_increment_on_response_sent) +{ + linkaddr_t peer_addr; + sixp_nbr_t *nbr; + sixp_trans_t *trans; + uint32_t body; + + UNIT_TEST_BEGIN(); + + test_setup(); + + peer_addr.u8[0] = 1; + UNIT_TEST_ASSERT((nbr = sixp_nbr_alloc(&peer_addr)) != NULL); + UNIT_TEST_ASSERT(sixp_nbr_set_next_seqno(nbr, 100) == 0); + UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 100); + + UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD, + TEST_SF_SFID, 10, + (const uint8_t *)&body, sizeof(body), NULL) + == 0); + + UNIT_TEST_ASSERT((trans = sixp_trans_find(&peer_addr)) == NULL); + sixp_input(packetbuf_hdrptr(), packetbuf_totlen(), &peer_addr); + UNIT_TEST_ASSERT((trans = sixp_trans_find(&peer_addr)) != NULL); + /* next_seqno must not be changed yet */ + UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 100); + UNIT_TEST_ASSERT(sixp_output(SIXP_PKT_TYPE_RESPONSE, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS, + TEST_SF_SFID, NULL, 0, &peer_addr, + NULL, NULL, 0) == 0); + UNIT_TEST_ASSERT(sixp_trans_transit_state(trans, + SIXP_TRANS_STATE_RESPONSE_SENT) + == 0); + /* + * next_seqno is overridden by the seqno of the request and + * incremented by 1 + */ + UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 11); + + UNIT_TEST_END(); +} + PROCESS_THREAD(test_process, ev, data) { static struct etimer et; @@ -1116,6 +1196,10 @@ PROCESS_THREAD(test_process, ev, data) UNIT_TEST_RUN(test_state_transition_invalid_transition_initiator); UNIT_TEST_RUN(test_state_transition_invalid_transition_responder); + /* seqno management*/ + UNIT_TEST_RUN(test_next_seqno_increment_on_request_sent); + UNIT_TEST_RUN(test_next_seqno_increment_on_response_sent); + printf("=check-me= DONE\n"); PROCESS_END(); } diff --git a/tests/16-6tisch/code/test-sixp.c b/tests/13-ieee802154/code-6tisch/test-sixp.c similarity index 70% rename from tests/16-6tisch/code/test-sixp.c rename to tests/13-ieee802154/code-6tisch/test-sixp.c index 2bf03a1e43f4a34a5904bc5ea24b779500c11120..91ad3283f241aac285410c26fb9bd8848dad7ced 100644 --- a/tests/16-6tisch/code/test-sixp.c +++ b/tests/13-ieee802154/code-6tisch/test-sixp.c @@ -93,7 +93,7 @@ UNIT_TEST(test_input_no_sf) memset(&body, 0, sizeof(body)); UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD, - UNKNOWN_SF_SFID, 10, 0, + UNKNOWN_SF_SFID, 10, (const uint8_t *)&body, sizeof(body), NULL) == 0); UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0); @@ -152,7 +152,7 @@ UNIT_TEST(test_input_busy) memset(&body, 0, sizeof(body)); UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD, - TEST_SF_SFID, 10, 0, + TEST_SF_SFID, 10, (const uint8_t *)&body, sizeof(body), NULL) == 0); UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0); @@ -174,7 +174,7 @@ UNIT_TEST(test_input_busy) /* 6top IE */ UNIT_TEST_ASSERT(p[4] == 0xc9); UNIT_TEST_ASSERT(p[5] == 0x10); - UNIT_TEST_ASSERT(p[6] == 0x07); + UNIT_TEST_ASSERT(p[6] == 0x08); UNIT_TEST_ASSERT(p[7] == TEST_SF_SFID); UNIT_TEST_ASSERT(p[8] == 0x0a); @@ -201,9 +201,9 @@ UNIT_TEST(test_input_no_memory) memset(&body, 0, sizeof(body)); UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD, - TEST_SF_SFID, 10, 0, + TEST_SF_SFID, 10, (const uint8_t *)&body, sizeof(body), - &pkt) == 0); + &pkt) == 0); memset(&addr, 0, sizeof(addr)); addr.u8[0] = 1; UNIT_TEST_ASSERT(sixp_trans_alloc(&pkt, &addr) != NULL); @@ -244,41 +244,6 @@ UNIT_TEST(test_input_no_memory) UNIT_TEST_END(); } -UNIT_TEST_REGISTER(test_input_schedule_generation, - "sixp_input(schedule_generation)"); -UNIT_TEST(test_input_schedule_generation) -{ - sixp_nbr_t *nbr; - sixp_trans_t *trans; - uint32_t body; - - UNIT_TEST_BEGIN(); - test_setup(); - memset(&body, 0, sizeof(body)); - - UNIT_TEST_ASSERT((nbr = sixp_nbr_alloc(&peer_addr)) != NULL); - /* nbr has GEN 0 now */ - - UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, - (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD, - TEST_SF_SFID, 10, 1, - (const uint8_t *)&body, sizeof(body), - NULL) == 0); - - sixp_input(packetbuf_hdrptr(), packetbuf_totlen(), &peer_addr); - UNIT_TEST_ASSERT(test_sf_input_is_called == 0); - - UNIT_TEST_ASSERT(sixp_nbr_advance_gen(nbr) == 0); - sixp_input(packetbuf_hdrptr(), packetbuf_totlen(), &peer_addr); - UNIT_TEST_ASSERT(test_sf_input_is_called == 1); - - UNIT_TEST_ASSERT((trans = sixp_trans_find(&peer_addr)) != NULL); - UNIT_TEST_ASSERT(sixp_trans_get_state(trans) == - SIXP_TRANS_STATE_REQUEST_RECEIVED); - - UNIT_TEST_END(); -} - UNIT_TEST_REGISTER(test_output_request_1, "sixp_output(request_1)"); UNIT_TEST(test_output_request_1) @@ -294,7 +259,7 @@ UNIT_TEST(test_output_request_1) UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD, - TEST_SF_SFID, 10, 0, + TEST_SF_SFID, 10, (const uint8_t *)&body, sizeof(body), &pkt) == 0); UNIT_TEST_ASSERT((trans = sixp_trans_alloc(&pkt, &peer_addr)) != NULL); @@ -360,7 +325,7 @@ UNIT_TEST(test_output_response_2) UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD, - TEST_SF_SFID, 10, 0, + TEST_SF_SFID, 10, (const uint8_t *)&body, sizeof(body), &pkt) == 0); UNIT_TEST_ASSERT((trans = sixp_trans_alloc(&pkt, &peer_addr)) != NULL); @@ -388,12 +353,12 @@ UNIT_TEST(test_output_response_3) UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD, - TEST_SF_SFID, 10, 0, + TEST_SF_SFID, 10, (const uint8_t *)&body, sizeof(body), &pkt) == 0); UNIT_TEST_ASSERT((trans = sixp_trans_alloc(&pkt, &peer_addr)) != NULL); UNIT_TEST_ASSERT( - sixp_trans_transit_state(trans, SIXP_TRANS_STATE_REQUEST_RECEIVED) == 0); + sixp_trans_transit_state(trans, SIXP_TRANS_STATE_REQUEST_RECEIVED) == 0); UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0); UNIT_TEST_ASSERT(sixp_output(SIXP_PKT_TYPE_RESPONSE, @@ -418,7 +383,7 @@ UNIT_TEST(test_output_response_4) UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD, - TEST_SF_SFID, 10, 0, + TEST_SF_SFID, 10, (const uint8_t *)&body, sizeof(body), &pkt) == 0); UNIT_TEST_ASSERT((trans = sixp_trans_alloc(&pkt, &peer_addr)) != NULL); @@ -467,7 +432,7 @@ UNIT_TEST(test_output_confirmation_2) UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD, - TEST_SF_SFID, 10, 0, + TEST_SF_SFID, 10, (const uint8_t *)&body, sizeof(body), &pkt) == 0); UNIT_TEST_ASSERT((trans = sixp_trans_alloc(&pkt, &peer_addr)) != NULL); @@ -495,7 +460,7 @@ UNIT_TEST(test_output_confirmation_3) UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD, - TEST_SF_SFID, 10, 0, + TEST_SF_SFID, 10, (const uint8_t *)&body, sizeof(body), &pkt) == 0); UNIT_TEST_ASSERT((trans = sixp_trans_alloc(&pkt, &peer_addr)) != NULL); @@ -527,7 +492,7 @@ UNIT_TEST(test_output_confirmation_4) UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD, - TEST_SF_SFID, 10, 0, + TEST_SF_SFID, 10, (const uint8_t *)&body, sizeof(body), &pkt) == 0); UNIT_TEST_ASSERT((trans = sixp_trans_alloc(&pkt, &peer_addr)) != NULL); @@ -549,6 +514,206 @@ UNIT_TEST(test_output_confirmation_4) UNIT_TEST_END(); } +UNIT_TEST_REGISTER(test_next_seqno_reset_by_clear_request_1, + "test if next_seqno is reset by sending CLEAR"); +UNIT_TEST(test_next_seqno_reset_by_clear_request_1) +{ + linkaddr_t peer_addr; + sixp_nbr_t *nbr; + sixp_trans_t *trans; + + UNIT_TEST_BEGIN(); + + test_setup(); + + /* + * When the node is the initiator of CLEAR, nbr->next_seqno must be + * reset to 0 regardless of the presence or absent of L2 ACK to the + * CLEAR Request. + */ + /* set next_seqno to 3 as the initial state for this sub-test */ + memset(&peer_addr, 0, sizeof(peer_addr)); + peer_addr.u8[0] = 1; + UNIT_TEST_ASSERT((nbr = sixp_nbr_alloc(&peer_addr)) != NULL); + UNIT_TEST_ASSERT(sixp_nbr_set_next_seqno(nbr, 3) == 0); + UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 3); + UNIT_TEST_ASSERT(sixp_output(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_CLEAR, + TEST_SF_SFID, NULL, 0, &peer_addr, + NULL, NULL, 0) == 0); + UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 0); + UNIT_TEST_ASSERT((trans = sixp_trans_find(&peer_addr)) != NULL); + UNIT_TEST_ASSERT(sixp_trans_transit_state(trans, + SIXP_TRANS_STATE_REQUEST_SENT) + == 0); + UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 0); + UNIT_TEST_ASSERT(sixp_trans_transit_state(trans, + SIXP_TRANS_STATE_TERMINATING) + == 0); + UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 0); + UNIT_TEST_END(); +} + +UNIT_TEST_REGISTER(test_next_seqno_reset_by_clear_request_2, + "test if next_seqno is reset by receiving CLEAR"); +UNIT_TEST(test_next_seqno_reset_by_clear_request_2) +{ + linkaddr_t peer_addr; + sixp_nbr_t *nbr; + sixp_pkt_metadata_t metadata; + + UNIT_TEST_BEGIN(); + + test_setup(); + + /* + * When the node is the responder of CLEAR, nbr->next_seqno must be + * reset to 0 regardless of the presence or absent of L2 ACK to the + * CLEAR Response. + */ + /* set next_seqno to 3 as the initial state for this sub-test */ + memset(&peer_addr, 0, sizeof(peer_addr)); + peer_addr.u8[0] = 1; + UNIT_TEST_ASSERT((nbr = sixp_nbr_alloc(&peer_addr)) != NULL); + UNIT_TEST_ASSERT(sixp_nbr_set_next_seqno(nbr, 3) == 0); + UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 3); + UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_CLEAR, + TEST_SF_SFID, 10, + (const uint8_t *)&metadata, + sizeof(metadata), NULL) == 0); + sixp_input(packetbuf_hdrptr(), packetbuf_totlen(), &peer_addr); + UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 0); + + UNIT_TEST_END(); +} + +UNIT_TEST_REGISTER(test_detect_seqno_error_1, + "test if seqno error is handled correctly (1)"); +UNIT_TEST(test_detect_seqno_error_1) +{ + linkaddr_t peer_addr; + uint32_t body; + uint8_t *p; + + UNIT_TEST_BEGIN(); + + test_setup(); + + memset(&peer_addr, 0, sizeof(peer_addr)); + peer_addr.u8[0] = 1; + UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD, + TEST_SF_SFID, 10, + (const uint8_t *)&body, + sizeof(body), NULL) == 0); + + /* return RC_ERR_RSEQNUM on receiving non-zero seqno when nbr doesn't exist */ + sixp_input(packetbuf_hdrptr(), packetbuf_totlen(), &peer_addr); + /* + * 2 octets for Termination 1 IE, one octet for 6top Sub-IE ID, and + * 2 octets for Payload IE Header. + */ + p = packetbuf_hdrptr() + 5; + /* now, p pointes to the 6P header */ + UNIT_TEST_ASSERT(packetbuf_totlen() == 11); + UNIT_TEST_ASSERT(p[0] == ((SIXP_PKT_TYPE_RESPONSE << 4) | SIXP_PKT_VERSION)); + UNIT_TEST_ASSERT(p[1] == SIXP_PKT_RC_ERR_SEQNUM); + UNIT_TEST_ASSERT(p[2] == TEST_SF_SFID); + UNIT_TEST_ASSERT(p[3] == 0); /* we don't have a relevant nbr; 0 is returned */ + + UNIT_TEST_END(); +} + +UNIT_TEST_REGISTER(test_detect_seqno_error_2, + "test if seqno error is handled correctly (2)"); +UNIT_TEST(test_detect_seqno_error_2) +{ + sixp_nbr_t *nbr; + sixp_trans_t *trans; + linkaddr_t peer_addr; + uint32_t body; + uint8_t *p; + + UNIT_TEST_BEGIN(); + + test_setup(); + + memset(&peer_addr, 0, sizeof(peer_addr)); + peer_addr.u8[0] = 1; + UNIT_TEST_ASSERT((nbr = sixp_nbr_alloc(&peer_addr)) != NULL); + UNIT_TEST_ASSERT(sixp_nbr_set_next_seqno(nbr, 3) == 0); + UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 3); + UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD, + TEST_SF_SFID, 0, + (const uint8_t *)&body, + sizeof(body), NULL) == 0); + + /* return RC_ERR_RSEQNUM on receiving zero when nbr->seqno is non-zero */ + sixp_input(packetbuf_hdrptr(), packetbuf_totlen(), &peer_addr); + /* + * 2 octets for Termination 1 IE, one octet for 6top Sub-IE ID, and + * 2 octets for Payload IE Header. + */ + p = packetbuf_hdrptr() + 5; + /* now, p pointes to the 6P header */ + UNIT_TEST_ASSERT(packetbuf_totlen() == 11); + UNIT_TEST_ASSERT(p[0] == ((SIXP_PKT_TYPE_RESPONSE << 4) | SIXP_PKT_VERSION)); + UNIT_TEST_ASSERT(p[1] == SIXP_PKT_RC_ERR_SEQNUM); + UNIT_TEST_ASSERT(p[2] == TEST_SF_SFID); + UNIT_TEST_ASSERT(p[3] == 3); + + UNIT_TEST_ASSERT((trans = sixp_trans_find(&peer_addr)) != NULL); + UNIT_TEST_ASSERT(sixp_trans_transit_state(trans, + SIXP_TRANS_STATE_RESPONSE_SENT) + == 0); + UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 4); + + UNIT_TEST_END(); +} + +UNIT_TEST_REGISTER(test_invalid_version, + "test invalid version"); +UNIT_TEST(test_invalid_version) +{ + linkaddr_t peer_addr; + uint8_t *p; + sixp_pkt_t pkt; + + UNIT_TEST_BEGIN(); + + test_setup(); + + memset(&peer_addr, 0, sizeof(peer_addr)); + peer_addr.u8[0] = 1; + UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST, + (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_CLEAR, + TEST_SF_SFID, 0, + NULL, 0, NULL) == 0); + p = packetbuf_hdrptr(); + p[0] |= 10; /* set version 10 which we doesn't support */ + /* this 6P packet shouldn't be parsed */ + UNIT_TEST_ASSERT(sixp_pkt_parse(packetbuf_hdrptr(), packetbuf_totlen(), + &pkt) == -1); + + /* return RC_ERR_VERSION on receiving zero when nbr->seqno is non-zero */ + sixp_input(packetbuf_hdrptr(), packetbuf_totlen(), &peer_addr); + /* + * 2 octets for Termination 1 IE, one octet for 6top Sub-IE ID, and + * 2 octets for Payload IE Header. + */ + p = packetbuf_hdrptr() + 5; + /* now, p pointes to the 6P header */ + UNIT_TEST_ASSERT(packetbuf_totlen() == 11); + UNIT_TEST_ASSERT(p[0] == ((SIXP_PKT_TYPE_RESPONSE << 4) | SIXP_PKT_VERSION)); + UNIT_TEST_ASSERT(p[1] == SIXP_PKT_RC_ERR_VERSION); + UNIT_TEST_ASSERT(p[2] == TEST_SF_SFID); + UNIT_TEST_ASSERT(p[3] == 0); + + UNIT_TEST_END(); +} + PROCESS_THREAD(test_process, ev, data) { static struct etimer et; @@ -571,7 +736,6 @@ PROCESS_THREAD(test_process, ev, data) UNIT_TEST_RUN(test_input_no_sf); UNIT_TEST_RUN(test_input_busy); UNIT_TEST_RUN(test_input_no_memory); - UNIT_TEST_RUN(test_input_schedule_generation); UNIT_TEST_RUN(test_output_request_1); UNIT_TEST_RUN(test_output_request_2); @@ -584,6 +748,14 @@ PROCESS_THREAD(test_process, ev, data) UNIT_TEST_RUN(test_output_confirmation_3); UNIT_TEST_RUN(test_output_confirmation_4); + /* testing for SeqNum Management */ + UNIT_TEST_RUN(test_next_seqno_reset_by_clear_request_1); + UNIT_TEST_RUN(test_next_seqno_reset_by_clear_request_2); + UNIT_TEST_RUN(test_detect_seqno_error_1); + UNIT_TEST_RUN(test_detect_seqno_error_2); + + UNIT_TEST_RUN(test_invalid_version); + printf("=check-me= DONE\n"); PROCESS_END(); } diff --git a/tests/16-6tisch/code/test-sixtop.c b/tests/13-ieee802154/code-6tisch/test-sixtop.c similarity index 100% rename from tests/16-6tisch/code/test-sixtop.c rename to tests/13-ieee802154/code-6tisch/test-sixtop.c diff --git a/tests/13-ieee802154/code-flush-nbr-queue/project-conf.h b/tests/13-ieee802154/code-flush-nbr-queue/project-conf.h index 6923ae6fbe1d83873553421ac6c9d5bbfa9f1581..039bc7c494181a38430fb43bbd2523a5669302da 100644 --- a/tests/13-ieee802154/code-flush-nbr-queue/project-conf.h +++ b/tests/13-ieee802154/code-flush-nbr-queue/project-conf.h @@ -29,8 +29,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _PROJECT_CONF_H_ -#define _PROJECT_CONF_H_ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ #define UNIT_TEST_PRINT_FUNCTION test_print_report @@ -41,4 +41,4 @@ #define TSCH_CONF_WITH_SIXTOP 1 -#endif /* __PROJECT_CONF_H__ */ +#endif /* PROJECT_CONF_H_ */ diff --git a/tests/13-ieee802154/code-flush-nbr-queue/test-flush-nbr-queue.c b/tests/13-ieee802154/code-flush-nbr-queue/test-flush-nbr-queue.c index 9045f77e4503676f58ee08728f8663c56fa47dbf..57324f26fae9655dff3dd7785b0406274ac96838 100644 --- a/tests/13-ieee802154/code-flush-nbr-queue/test-flush-nbr-queue.c +++ b/tests/13-ieee802154/code-flush-nbr-queue/test-flush-nbr-queue.c @@ -38,7 +38,6 @@ #include "net/linkaddr.h" #include "net/mac/tsch/tsch.h" -#include "net/mac/tsch/tsch-queue.h" #include "unit-test/unit-test.h" #include "common.h" @@ -58,7 +57,7 @@ UNIT_TEST(test) UNIT_TEST_BEGIN(); - packet = tsch_queue_add_packet(TEST_PEER_ADDR, NULL, NULL); + packet = tsch_queue_add_packet(TEST_PEER_ADDR, 1, NULL, NULL); UNIT_TEST_ASSERT(packet != NULL); nbr = tsch_queue_get_nbr(TEST_PEER_ADDR); @@ -68,14 +67,14 @@ UNIT_TEST(test) * QUEUEBUF_CONF_NUM is set with 1; so another addition should fail due to * lack of memory. */ - packet = tsch_queue_add_packet(TEST_PEER_ADDR, NULL, NULL); + packet = tsch_queue_add_packet(TEST_PEER_ADDR, 1, NULL, NULL); UNIT_TEST_ASSERT(packet == NULL); /* tsch_queue_flush_nbr_queue() is called inside of tsch_queue_reset(). */ tsch_queue_reset(); /* After flushing the nbr queue, we should be able to add a new packet */ - packet = tsch_queue_add_packet(TEST_PEER_ADDR, NULL, NULL); + packet = tsch_queue_add_packet(TEST_PEER_ADDR, 1, NULL, NULL); UNIT_TEST_ASSERT(packet != NULL); UNIT_TEST_END(); diff --git a/tests/13-ieee802154/code/Makefile b/tests/13-ieee802154/code-panid-handling/Makefile similarity index 100% rename from tests/13-ieee802154/code/Makefile rename to tests/13-ieee802154/code-panid-handling/Makefile diff --git a/tests/13-ieee802154/code/project-conf.h b/tests/13-ieee802154/code-panid-handling/project-conf.h similarity index 95% rename from tests/13-ieee802154/code/project-conf.h rename to tests/13-ieee802154/code-panid-handling/project-conf.h index 5c17b28a29c764125b58f5c8cd6a483fdab9b807..89b2c289e47e9e52ae2f2680717fd86286f4ea30 100644 --- a/tests/13-ieee802154/code/project-conf.h +++ b/tests/13-ieee802154/code-panid-handling/project-conf.h @@ -29,8 +29,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _PROJECT_CONF_H_ -#define _PROJECT_CONF_H_ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ #define UNIT_TEST_PRINT_FUNCTION test_print_report @@ -38,4 +38,4 @@ #include "project-tsch-conf.h" #endif /* MAC_CONF_WITH_TSCH */ -#endif /* !_PROJECT_CONF_H_ */ +#endif /* !PROJECT_CONF_H_ */ diff --git a/tests/13-ieee802154/code/project-tsch-conf.h b/tests/13-ieee802154/code-panid-handling/project-tsch-conf.h similarity index 100% rename from tests/13-ieee802154/code/project-tsch-conf.h rename to tests/13-ieee802154/code-panid-handling/project-tsch-conf.h diff --git a/tests/13-ieee802154/code/test-panid-handling.c b/tests/13-ieee802154/code-panid-handling/test-panid-handling.c similarity index 100% rename from tests/13-ieee802154/code/test-panid-handling.c rename to tests/13-ieee802154/code-panid-handling/test-panid-handling.c diff --git a/tests/16-6tisch/js/unit-test.js b/tests/13-ieee802154/js/sixtop-test.js similarity index 99% rename from tests/16-6tisch/js/unit-test.js rename to tests/13-ieee802154/js/sixtop-test.js index 962182e33c30c381b6ab9dbbc101ae01f676f3a0..c410644ec296f3054caecb873211f270abac47aa 100644 --- a/tests/16-6tisch/js/unit-test.js +++ b/tests/13-ieee802154/js/sixtop-test.js @@ -24,4 +24,3 @@ if(failed) { log.testFailed(); } log.testOK(); - diff --git a/tests/14-rpl-lite/01-rpl-up-route.csc b/tests/14-rpl-lite/01-rpl-up-route.csc index 7c6996a51ef5da2e7076465fc4c2e14c757cfe08..899b58bf7a9f9b9a165132f33fd0ab7eb8518cf2 100644 --- a/tests/14-rpl-lite/01-rpl-up-route.csc +++ b/tests/14-rpl-lite/01-rpl-up-route.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make TARGET=cooja clean -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make TARGET=cooja clean -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make TARGET=cooja clean -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> diff --git a/tests/14-rpl-lite/03-rpl-28-hours.csc b/tests/14-rpl-lite/03-rpl-28-hours.csc index 98fe096ea83eeb2963931cfc1b29fb38cf9d7341..a4c25cc08012c1f61e5af7171f4a38ba521a0a6c 100644 --- a/tests/14-rpl-lite/03-rpl-28-hours.csc +++ b/tests/14-rpl-lite/03-rpl-28-hours.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make TARGET=cooja clean -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make TARGET=cooja clean -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make TARGET=cooja clean -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> diff --git a/tests/14-rpl-lite/05-rpl-up-and-down-routes.csc b/tests/14-rpl-lite/05-rpl-up-and-down-routes.csc index 0dd110738d58d168058d0a05cb8014ba92a0f8a5..49e7936915278a78772445b7accdc10ae88842d8 100644 --- a/tests/14-rpl-lite/05-rpl-up-and-down-routes.csc +++ b/tests/14-rpl-lite/05-rpl-up-and-down-routes.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -339,4 +338,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/14-rpl-lite/06-rpl-temporary-root-loss.csc b/tests/14-rpl-lite/06-rpl-temporary-root-loss.csc index 6c29c643f9ec77745b378dd3a1ee5a3dcd02b94a..6d8283d3e8f2b6727dcbb31ec21ca220403e5dc1 100644 --- a/tests/14-rpl-lite/06-rpl-temporary-root-loss.csc +++ b/tests/14-rpl-lite/06-rpl-temporary-root-loss.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -345,4 +344,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/14-rpl-lite/07-rpl-random-rearrangement.csc b/tests/14-rpl-lite/07-rpl-random-rearrangement.csc index cdb62c42083f0ac533395e5ced88067b1ba8914e..6119c6829f5f6c08152264c1b4cd8040e1018229 100644 --- a/tests/14-rpl-lite/07-rpl-random-rearrangement.csc +++ b/tests/14-rpl-lite/07-rpl-random-rearrangement.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -544,7 +543,7 @@ make receiver-node.cooja TARGET=cooja</commands> }
 
 function getRandom(min, max) {
 - return Math.random() * (max - min) + min;
 + return r.nextFloat() * (max - min) + min;
 }
 
 // From: http://bost.ocks.org/mike/shuffle/
 @@ -555,7 +554,7 @@ function shuffle(array) {
 while (m) {
 
 // Pick a remaining element…
 - i = Math.floor(Math.random() * m--);
 + i = Math.floor(r.nextFloat() * m--);
 
 // And swap it with the current element.
 t = array[m];
 @@ -571,6 +570,7 @@ GENERATE_MSG(1200000, 'randomize-nodes');
 GENERATE_MSG(2400000, 'randomize-nodes');
 GENERATE_MSG(3600000, 'randomize-nodes');
 
 +var r = new java.util.Random(sim.getRandomSeed());
 var numForwarders = 20;
 var forwardIDStart = 4;
 packetsReceived = [];
 @@ -644,4 +644,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/14-rpl-lite/08-rpl-dao-route-loss-0.csc b/tests/14-rpl-lite/08-rpl-dao-route-loss-0.csc index 0fc6e032d80340de0e5f218e6e2d0fcb4b042943..bd1114c509b91c4f0ff4e6ddc079d87015b59799 100644 --- a/tests/14-rpl-lite/08-rpl-dao-route-loss-0.csc +++ b/tests/14-rpl-lite/08-rpl-dao-route-loss-0.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -357,4 +356,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/14-rpl-lite/08-rpl-dao-route-loss-1.csc b/tests/14-rpl-lite/08-rpl-dao-route-loss-1.csc index 2c0ce41fffeb06630a0a1992afaadb969fabba76..cc1fd397015e63bdd6391e800d91e75d07b7bce4 100644 --- a/tests/14-rpl-lite/08-rpl-dao-route-loss-1.csc +++ b/tests/14-rpl-lite/08-rpl-dao-route-loss-1.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -357,4 +356,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/14-rpl-lite/08-rpl-dao-route-loss-2.csc b/tests/14-rpl-lite/08-rpl-dao-route-loss-2.csc index cdb2bd748fe228ccef96080be2a05d8515012638..f659b4e04f5c750e998800e710c9d12bc4cc81aa 100644 --- a/tests/14-rpl-lite/08-rpl-dao-route-loss-2.csc +++ b/tests/14-rpl-lite/08-rpl-dao-route-loss-2.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -357,4 +356,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/14-rpl-lite/08-rpl-dao-route-loss-3.csc b/tests/14-rpl-lite/08-rpl-dao-route-loss-3.csc index 34b930c0d7813c98cb06fcf48724882db6a624a0..a3e38edac6990c4acb90fabd392deb843badddb0 100644 --- a/tests/14-rpl-lite/08-rpl-dao-route-loss-3.csc +++ b/tests/14-rpl-lite/08-rpl-dao-route-loss-3.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -357,4 +356,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/14-rpl-lite/08-rpl-dao-route-loss-4.csc b/tests/14-rpl-lite/08-rpl-dao-route-loss-4.csc index ff9a400c1efc71f5574ab723007dc04ca573f1f2..11a0f3168088a635c57350a02c4fca316d4b8c0e 100644 --- a/tests/14-rpl-lite/08-rpl-dao-route-loss-4.csc +++ b/tests/14-rpl-lite/08-rpl-dao-route-loss-4.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -357,4 +356,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/14-rpl-lite/08-rpl-dao-route-loss-5.csc b/tests/14-rpl-lite/08-rpl-dao-route-loss-5.csc index e491b666f721a5da48416bf9ea884b9b3f8ee0e4..0a0308e22a4292f60045fe3d6234201cb90a2542 100644 --- a/tests/14-rpl-lite/08-rpl-dao-route-loss-5.csc +++ b/tests/14-rpl-lite/08-rpl-dao-route-loss-5.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -357,4 +356,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/14-rpl-lite/09-rpl-probing.csc b/tests/14-rpl-lite/09-rpl-probing.csc index 7e5ef727a752799785e6432135f00d862ebaf519..d79ec7be4cbf67fdd1293ba5bd9cd59393cda954 100644 --- a/tests/14-rpl-lite/09-rpl-probing.csc +++ b/tests/14-rpl-lite/09-rpl-probing.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> diff --git a/tests/14-rpl-lite/code/project-conf.h b/tests/14-rpl-lite/code/project-conf.h index 599ac1cbf5cd0ccd1318647aeaf34cb2ae41e681..d6cd59471761d9f6bad11e269fa2bbb10c8fbe91 100644 --- a/tests/14-rpl-lite/code/project-conf.h +++ b/tests/14-rpl-lite/code/project-conf.h @@ -27,5 +27,3 @@ * SUCH DAMAGE. */ #define TCPIP_CONF_ANNOTATE_TRANSMISSIONS 1 - -#define RPL_CONF_MOP RPL_MOP_NON_STORING diff --git a/tests/14-rpl-lite/code/receiver-node.c b/tests/14-rpl-lite/code/receiver-node.c index 352f23cb501c304f1d3aea5ecd4db9f0982a7f6c..b5265d3f7f3f8bebd57d503a5d43a35d0e48ee33 100644 --- a/tests/14-rpl-lite/code/receiver-node.c +++ b/tests/14-rpl-lite/code/receiver-node.c @@ -38,7 +38,7 @@ #include "simple-udp.h" -#include "rpl.h" +#include "net/routing/routing.h" #include "dev/leds.h" #include <stdio.h> diff --git a/tests/14-rpl-lite/code/root-node.c b/tests/14-rpl-lite/code/root-node.c index ef3c982ee14aaed84391efbd80e8967244dc7ac9..7c9fc8c99c59ceb5e555a996cf3142f18af95c02 100644 --- a/tests/14-rpl-lite/code/root-node.c +++ b/tests/14-rpl-lite/code/root-node.c @@ -38,8 +38,7 @@ #include "simple-udp.h" -#include "rpl.h" -#include "rpl-dag-root.h" +#include "net/routing/routing.h" #include <stdio.h> #include <string.h> @@ -75,7 +74,7 @@ PROCESS_THREAD(unicast_receiver_process, ev, data) { PROCESS_BEGIN(); - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_start(); simple_udp_register(&unicast_connection, UDP_PORT, NULL, UDP_PORT, receiver); diff --git a/tests/15-rpl-classic/01-rpl-up-route.csc b/tests/15-rpl-classic/01-rpl-up-route.csc index 7c6996a51ef5da2e7076465fc4c2e14c757cfe08..899b58bf7a9f9b9a165132f33fd0ab7eb8518cf2 100644 --- a/tests/15-rpl-classic/01-rpl-up-route.csc +++ b/tests/15-rpl-classic/01-rpl-up-route.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make TARGET=cooja clean -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make TARGET=cooja clean -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make TARGET=cooja clean -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> diff --git a/tests/15-rpl-classic/02-rpl-root-reboot.csc b/tests/15-rpl-classic/02-rpl-root-reboot.csc index 32dbbd28b0d0c11396be7afc3c14a0a89509fa11..2c89a499ee862f5f5a511421da97d5ecb269826f 100644 --- a/tests/15-rpl-classic/02-rpl-root-reboot.csc +++ b/tests/15-rpl-classic/02-rpl-root-reboot.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make TARGET=cooja clean -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make TARGET=cooja clean -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make TARGET=cooja clean -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -341,4 +340,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/15-rpl-classic/03-rpl-28-hours.csc b/tests/15-rpl-classic/03-rpl-28-hours.csc index 98fe096ea83eeb2963931cfc1b29fb38cf9d7341..a4c25cc08012c1f61e5af7171f4a38ba521a0a6c 100644 --- a/tests/15-rpl-classic/03-rpl-28-hours.csc +++ b/tests/15-rpl-classic/03-rpl-28-hours.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make TARGET=cooja clean -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make TARGET=cooja clean -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make TARGET=cooja clean -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> diff --git a/tests/15-rpl-classic/05-rpl-up-and-down-routes-non-storing.csc b/tests/15-rpl-classic/05-rpl-up-and-down-routes-non-storing.csc new file mode 100644 index 0000000000000000000000000000000000000000..aa412586b90d28d4379139b86376d256ef9e6692 --- /dev/null +++ b/tests/15-rpl-classic/05-rpl-up-and-down-routes-non-storing.csc @@ -0,0 +1,341 @@ +<?xml version="1.0" encoding="UTF-8"?> +<simconf> + <project EXPORT="discard">[APPS_DIR]/mrm</project> + <project EXPORT="discard">[APPS_DIR]/mspsim</project> + <project EXPORT="discard">[APPS_DIR]/avrora</project> + <project EXPORT="discard">[APPS_DIR]/serial_socket</project> + <project EXPORT="discard">[APPS_DIR]/collect-view</project> + <project EXPORT="discard">[APPS_DIR]/powertracker</project> + <simulation> + <title>My simulation</title> + <randomseed>123456</randomseed> + <motedelay_us>1000000</motedelay_us> + <radiomedium> + org.contikios.cooja.radiomediums.UDGM + <transmitting_range>50.0</transmitting_range> + <interference_range>50.0</interference_range> + <success_ratio_tx>1.0</success_ratio_tx> + <success_ratio_rx>1.0</success_ratio_rx> + </radiomedium> + <events> + <logoutput>40000</logoutput> + </events> + <motetype> + org.contikios.cooja.contikimote.ContikiMoteType + <identifier>mtype743</identifier> + <description>Sender</description> + <source>[CONFIG_DIR]/code/sender-node.c</source> + <commands>make clean TARGET=cooja +make -j sender-node.cooja TARGET=cooja DEFINES=RPL_CONF_MOP=RPL_MOP_NON_STORING</commands> + <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> + <symbols>false</symbols> + </motetype> + <motetype> + org.contikios.cooja.contikimote.ContikiMoteType + <identifier>mtype452</identifier> + <description>RPL root</description> + <source>[CONFIG_DIR]/code/root-node.c</source> + <commands>make clean TARGET=cooja +make -j root-node.cooja TARGET=cooja DEFINES=RPL_CONF_MOP=RPL_MOP_NON_STORING</commands> + <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> + <symbols>false</symbols> + </motetype> + <motetype> + org.contikios.cooja.contikimote.ContikiMoteType + <identifier>mtype782</identifier> + <description>Receiver</description> + <source>[CONFIG_DIR]/code/receiver-node.c</source> + <commands>make clean TARGET=cooja +make -j receiver-node.cooja TARGET=cooja DEFINES=RPL_CONF_MOP=RPL_MOP_NON_STORING</commands> + <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> + <symbols>false</symbols> + </motetype> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>-22.5728586847096</x> + <y>123.9358664968653</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>1</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <motetype_identifier>mtype782</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>116.13379149678028</x> + <y>88.36698920455684</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>2</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <motetype_identifier>mtype743</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>-1.39303771455413</x> + <y>100.21446701029119</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>4</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <motetype_identifier>mtype782</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>95.25095618820441</x> + <y>63.14998053005015</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>5</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <motetype_identifier>mtype782</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>66.09378990830604</x> + <y>38.32698761608261</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>6</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <motetype_identifier>mtype782</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>29.05630841762433</x> + <y>30.840688165838436</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>7</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <motetype_identifier>mtype782</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>10.931583432822638</x> + <y>69.848248459216</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>8</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <motetype_identifier>mtype782</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>0.0</x> + <y>0.0</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>3</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <motetype_identifier>mtype452</motetype_identifier> + </mote> + </simulation> + <plugin> + org.contikios.cooja.plugins.SimControl + <width>280</width> + <z>1</z> + <height>160</height> + <location_x>400</location_x> + <location_y>0</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.Visualizer + <plugin_config> + <skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin> + <skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin> + <skin>org.contikios.cooja.plugins.skins.GridVisualizerSkin</skin> + <skin>org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin</skin> + <viewport>2.5379695437350276 0.0 0.0 2.5379695437350276 75.2726010197627 15.727272727272757</viewport> + </plugin_config> + <width>400</width> + <z>2</z> + <height>400</height> + <location_x>1</location_x> + <location_y>1</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.LogListener + <plugin_config> + <filter /> + </plugin_config> + <width>1184</width> + <z>3</z> + <height>240</height> + <location_x>402</location_x> + <location_y>162</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.Notes + <plugin_config> + <notes>Enter notes here</notes> + <decorations>true</decorations> + </plugin_config> + <width>904</width> + <z>4</z> + <height>160</height> + <location_x>680</location_x> + <location_y>0</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.ScriptRunner + <plugin_config> + <script>GENERATE_MSG(0000000, "add-sink");
 +//GENERATE_MSG(1000000, "remove-sink");
 +//GENERATE_MSG(1020000, "add-sink");
 +
 +lostMsgs = 0;
 +
 +TIMEOUT(1000000, if(lostMsgs == 0) { log.testOK(); } );
 +
 +lastMsg = -1;
 +packets = "_________";
 +hops = 0;
 +
 +while(true) {
 + YIELD();
 + if(msg.equals("remove-sink")) {
 + m = sim.getMoteWithID(3);
 + sim.removeMote(m);
 + log.log("removed sink\n");
 + } else if(msg.equals("add-sink")) {
 + if(!sim.getMoteWithID(3)) {
 + m = sim.getMoteTypes()[1].generateMote(sim);
 + m.getInterfaces().getMoteID().setMoteID(3);
 + sim.addMote(m);
 + log.log("added sink\n");
 + } else {
 + log.log("did not add sink as it was already there\n"); 
 + }
 + } else if(msg.startsWith("Sending")) {
 + hops = 0;
 + } else if(msg.startsWith("#L") && msg.endsWith("1; red")) {
 + hops++;
 + } else if(msg.startsWith("Data")) {
 + data = msg.split(" ");
 + num = parseInt(data[14]);
 + if(lastMsg != -1) {
 + if(num != lastMsg + 1) {
 + numMissed = num - lastMsg - 1;
 + lostMsgs += numMissed; 
 + log.log("Missed messages " + numMissed + " before " + num + "\n"); 
 + for(i = 0; i < numMissed; i++) {
 + packets = packets.substr(0, lastMsg + i + 1).concat("_"); 
 + }
 + } 
 + }
 + packets = packets.substr(0, num).concat("*");
 + log.log("" + hops + " " + packets + "\n");
 + lastMsg = num;
 + }
 +}</script> + <active>true</active> + </plugin_config> + <width>962</width> + <z>0</z> + <height>596</height> + <location_x>603</location_x> + <location_y>43</location_y> + </plugin> +</simconf> diff --git a/tests/15-rpl-classic/05-rpl-up-and-down-routes.csc b/tests/15-rpl-classic/05-rpl-up-and-down-routes.csc index 0dd110738d58d168058d0a05cb8014ba92a0f8a5..49e7936915278a78772445b7accdc10ae88842d8 100644 --- a/tests/15-rpl-classic/05-rpl-up-and-down-routes.csc +++ b/tests/15-rpl-classic/05-rpl-up-and-down-routes.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -339,4 +338,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/15-rpl-classic/06-rpl-temporary-root-loss.csc b/tests/15-rpl-classic/06-rpl-temporary-root-loss.csc index 602ad0e23c243decf0286dd1990839a3cd459748..9bbf552d508a79efc430a9a2c1d6951a192ff1e1 100644 --- a/tests/15-rpl-classic/06-rpl-temporary-root-loss.csc +++ b/tests/15-rpl-classic/06-rpl-temporary-root-loss.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -345,4 +344,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/15-rpl-classic/07-rpl-random-rearrangement.csc b/tests/15-rpl-classic/07-rpl-random-rearrangement.csc index cdb62c42083f0ac533395e5ced88067b1ba8914e..6119c6829f5f6c08152264c1b4cd8040e1018229 100644 --- a/tests/15-rpl-classic/07-rpl-random-rearrangement.csc +++ b/tests/15-rpl-classic/07-rpl-random-rearrangement.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -544,7 +543,7 @@ make receiver-node.cooja TARGET=cooja</commands> }
 
 function getRandom(min, max) {
 - return Math.random() * (max - min) + min;
 + return r.nextFloat() * (max - min) + min;
 }
 
 // From: http://bost.ocks.org/mike/shuffle/
 @@ -555,7 +554,7 @@ function shuffle(array) {
 while (m) {
 
 // Pick a remaining element…
 - i = Math.floor(Math.random() * m--);
 + i = Math.floor(r.nextFloat() * m--);
 
 // And swap it with the current element.
 t = array[m];
 @@ -571,6 +570,7 @@ GENERATE_MSG(1200000, 'randomize-nodes');
 GENERATE_MSG(2400000, 'randomize-nodes');
 GENERATE_MSG(3600000, 'randomize-nodes');
 
 +var r = new java.util.Random(sim.getRandomSeed());
 var numForwarders = 20;
 var forwardIDStart = 4;
 packetsReceived = [];
 @@ -644,4 +644,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/15-rpl-classic/08-rpl-dao-route-loss-0.csc b/tests/15-rpl-classic/08-rpl-dao-route-loss-0.csc index 0fc6e032d80340de0e5f218e6e2d0fcb4b042943..bd1114c509b91c4f0ff4e6ddc079d87015b59799 100644 --- a/tests/15-rpl-classic/08-rpl-dao-route-loss-0.csc +++ b/tests/15-rpl-classic/08-rpl-dao-route-loss-0.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -357,4 +356,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/15-rpl-classic/08-rpl-dao-route-loss-1.csc b/tests/15-rpl-classic/08-rpl-dao-route-loss-1.csc index 2c0ce41fffeb06630a0a1992afaadb969fabba76..cc1fd397015e63bdd6391e800d91e75d07b7bce4 100644 --- a/tests/15-rpl-classic/08-rpl-dao-route-loss-1.csc +++ b/tests/15-rpl-classic/08-rpl-dao-route-loss-1.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -357,4 +356,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/15-rpl-classic/08-rpl-dao-route-loss-2.csc b/tests/15-rpl-classic/08-rpl-dao-route-loss-2.csc index cdb2bd748fe228ccef96080be2a05d8515012638..f659b4e04f5c750e998800e710c9d12bc4cc81aa 100644 --- a/tests/15-rpl-classic/08-rpl-dao-route-loss-2.csc +++ b/tests/15-rpl-classic/08-rpl-dao-route-loss-2.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -357,4 +356,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/15-rpl-classic/08-rpl-dao-route-loss-3.csc b/tests/15-rpl-classic/08-rpl-dao-route-loss-3.csc index 34b930c0d7813c98cb06fcf48724882db6a624a0..a3e38edac6990c4acb90fabd392deb843badddb0 100644 --- a/tests/15-rpl-classic/08-rpl-dao-route-loss-3.csc +++ b/tests/15-rpl-classic/08-rpl-dao-route-loss-3.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -357,4 +356,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/15-rpl-classic/08-rpl-dao-route-loss-4.csc b/tests/15-rpl-classic/08-rpl-dao-route-loss-4.csc index ff9a400c1efc71f5574ab723007dc04ca573f1f2..11a0f3168088a635c57350a02c4fca316d4b8c0e 100644 --- a/tests/15-rpl-classic/08-rpl-dao-route-loss-4.csc +++ b/tests/15-rpl-classic/08-rpl-dao-route-loss-4.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -357,4 +356,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/15-rpl-classic/08-rpl-dao-route-loss-5.csc b/tests/15-rpl-classic/08-rpl-dao-route-loss-5.csc index e491b666f721a5da48416bf9ea884b9b3f8ee0e4..0a0308e22a4292f60045fe3d6234201cb90a2542 100644 --- a/tests/15-rpl-classic/08-rpl-dao-route-loss-5.csc +++ b/tests/15-rpl-classic/08-rpl-dao-route-loss-5.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -357,4 +356,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/15-rpl-classic/09-rpl-probing.csc b/tests/15-rpl-classic/09-rpl-probing.csc index 7e5ef727a752799785e6432135f00d862ebaf519..d79ec7be4cbf67fdd1293ba5bd9cd59393cda954 100644 --- a/tests/15-rpl-classic/09-rpl-probing.csc +++ b/tests/15-rpl-classic/09-rpl-probing.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> <title>My simulation</title> @@ -26,7 +25,7 @@ <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> <commands>make clean TARGET=cooja -make sender-node.cooja TARGET=cooja</commands> +make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ make sender-node.cooja TARGET=cooja</commands> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> <commands>make clean TARGET=cooja -make root-node.cooja TARGET=cooja</commands> +make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -76,7 +75,7 @@ make root-node.cooja TARGET=cooja</commands> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> <commands>make clean TARGET=cooja -make receiver-node.cooja TARGET=cooja</commands> +make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> diff --git a/tests/15-rpl-classic/10-rpl-multi-dodag.csc b/tests/15-rpl-classic/10-rpl-multi-dodag.csc index 685846492fe443dace870562c4eed2ab00f2223f..7d48ae7b49407244dcac8f1977ce104fe0fd4c2b 100644 --- a/tests/15-rpl-classic/10-rpl-multi-dodag.csc +++ b/tests/15-rpl-classic/10-rpl-multi-dodag.csc @@ -4,7 +4,6 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <project EXPORT="discard">[APPS_DIR]/serial2pty</project> <project EXPORT="discard">[APPS_DIR]/radiologger-headless</project> @@ -27,7 +26,7 @@ <identifier>mtype301</identifier> <description>Sender</description> <source>[CONFIG_DIR]/code/sender-node.c</source> - <commands>make sender-node.cooja TARGET=cooja</commands> + <commands>make -j sender-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -51,7 +50,7 @@ <identifier>mtype820</identifier> <description>RPL root</description> <source>[CONFIG_DIR]/code/root-node.c</source> - <commands>make root-node.cooja TARGET=cooja</commands> + <commands>make -j root-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -75,7 +74,7 @@ <identifier>mtype306</identifier> <description>Receiver</description> <source>[CONFIG_DIR]/code/receiver-node.c</source> - <commands>make receiver-node.cooja TARGET=cooja</commands> + <commands>make -j receiver-node.cooja TARGET=cooja</commands> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> @@ -386,4 +385,3 @@ while(true) {
 <location_y>43</location_y> </plugin> </simconf> - diff --git a/tests/15-rpl-classic/code/receiver-node.c b/tests/15-rpl-classic/code/receiver-node.c index 770f50f77028c1ac403c0ff57004945d4f62d4bd..20bf165f8bbdb1169edd1cbb5dafbfe04203bbe5 100644 --- a/tests/15-rpl-classic/code/receiver-node.c +++ b/tests/15-rpl-classic/code/receiver-node.c @@ -38,7 +38,7 @@ #include "simple-udp.h" -#include "rpl.h" +#include "net/routing/routing.h" #include "dev/leds.h" #include <stdio.h> @@ -91,6 +91,7 @@ set_global_address(void) return &ipaddr; } /*---------------------------------------------------------------------------*/ +#if RPL_WITH_STORING uint8_t should_blink = 1; static void route_callback(int event, uip_ipaddr_t *route, uip_ipaddr_t *ipaddr, int num_routes) @@ -101,17 +102,22 @@ route_callback(int event, uip_ipaddr_t *route, uip_ipaddr_t *ipaddr, int num_rou should_blink = 1; } } +#endif /* #if RPL_WITH_STORING */ /*---------------------------------------------------------------------------*/ PROCESS_THREAD(receiver_node_process, ev, data) { static struct etimer et; +#if RPL_WITH_STORING static struct uip_ds6_notification n; +#endif /* #if RPL_WITH_STORING */ PROCESS_BEGIN(); set_global_address(); +#if RPL_WITH_STORING uip_ds6_notification_add(&n, route_callback); +#endif /* #if RPL_WITH_STORING */ simple_udp_register(&unicast_connection, UDP_PORT, NULL, UDP_PORT, receiver); @@ -120,12 +126,14 @@ PROCESS_THREAD(receiver_node_process, ev, data) while(1) { PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); etimer_reset(&et); +#if RPL_WITH_STORING if(should_blink) { leds_on(LEDS_ALL); PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); etimer_reset(&et); leds_off(LEDS_ALL); } +#endif /* #if RPL_WITH_STORING */ } PROCESS_END(); } diff --git a/tests/15-rpl-classic/code/root-node.c b/tests/15-rpl-classic/code/root-node.c index ef3c982ee14aaed84391efbd80e8967244dc7ac9..e25b2872fb0037e8d4fee5690293d4974bd6643f 100644 --- a/tests/15-rpl-classic/code/root-node.c +++ b/tests/15-rpl-classic/code/root-node.c @@ -35,12 +35,9 @@ #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip-debug.h" - +#include "net/routing/routing.h" #include "simple-udp.h" -#include "rpl.h" -#include "rpl-dag-root.h" - #include <stdio.h> #include <string.h> @@ -75,7 +72,7 @@ PROCESS_THREAD(unicast_receiver_process, ev, data) { PROCESS_BEGIN(); - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_start(); simple_udp_register(&unicast_connection, UDP_PORT, NULL, UDP_PORT, receiver); diff --git a/tests/16-6tisch/03-cooja-test-sixp-trans.csc b/tests/16-6tisch/03-cooja-test-sixp-trans.csc deleted file mode 100644 index e187a44f49203bc05f4f286fed5aeeb7f39e2e02..0000000000000000000000000000000000000000 --- a/tests/16-6tisch/03-cooja-test-sixp-trans.csc +++ /dev/null @@ -1,163 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<simconf> - <project EXPORT="discard">[APPS_DIR]/mrm</project> - <project EXPORT="discard">[APPS_DIR]/mspsim</project> - <project EXPORT="discard">[APPS_DIR]/avrora</project> - <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> - <project EXPORT="discard">[APPS_DIR]/powertracker</project> - <simulation> - <title>My simulation</title> - <randomseed>123456</randomseed> - <motedelay_us>1000000</motedelay_us> - <radiomedium> - org.contikios.cooja.radiomediums.UDGM - <transmitting_range>50.0</transmitting_range> - <interference_range>100.0</interference_range> - <success_ratio_tx>1.0</success_ratio_tx> - <success_ratio_rx>1.0</success_ratio_rx> - </radiomedium> - <events> - <logoutput>40000</logoutput> - </events> - <motetype> - org.contikios.cooja.contikimote.ContikiMoteType - <identifier>mtype382</identifier> - <description>Cooja Mote Type #1</description> - <source>[CONTIKI_DIR]/tests/16-6tisch/code/test-sixp-trans.c</source> - <commands>make clean TARGET=cooja - make test-sixp-trans.cooja TARGET=cooja</commands> - <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> - <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> - <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface> - <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface> - <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> - <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface> - <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface> - <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface> - <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface> - <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface> - <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface> - <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface> - <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> - <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> - <symbols>false</symbols> - </motetype> - <mote> - <interface_config> - org.contikios.cooja.interfaces.Position - <x>47.60131881808453</x> - <y>20.028921031789082</y> - <z>0.0</z> - </interface_config> - <interface_config> - org.contikios.cooja.contikimote.interfaces.ContikiMoteID - <id>1</id> - </interface_config> - <interface_config> - org.contikios.cooja.contikimote.interfaces.ContikiRadio - <bitrate>250.0</bitrate> - </interface_config> - <interface_config> - org.contikios.cooja.contikimote.interfaces.ContikiEEPROM - <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> - </interface_config> - <motetype_identifier>mtype382</motetype_identifier> - </mote> - </simulation> - <plugin> - org.contikios.cooja.plugins.SimControl - <width>280</width> - <z>5</z> - <height>160</height> - <location_x>400</location_x> - <location_y>0</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.Visualizer - <plugin_config> - <moterelations>true</moterelations> - <skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.GridVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.TrafficVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin> - <viewport>0.9090909090909091 0.0 0.0 0.9090909090909091 150.72607380174134 154.79188997110083</viewport> - </plugin_config> - <width>400</width> - <z>4</z> - <height>400</height> - <location_x>1</location_x> - <location_y>1</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.LogListener - <plugin_config> - <filter /> - <formatted_time /> - <coloring /> - </plugin_config> - <width>1320</width> - <z>3</z> - <height>240</height> - <location_x>400</location_x> - <location_y>160</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.TimeLine - <plugin_config> - <mote>0</mote> - <showRadioRXTX /> - <showRadioHW /> - <showLEDs /> - <zoomfactor>500.0</zoomfactor> - </plugin_config> - <width>1720</width> - <z>2</z> - <height>166</height> - <location_x>0</location_x> - <location_y>957</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.Notes - <plugin_config> - <notes>Enter notes here</notes> - <decorations>true</decorations> - </plugin_config> - <width>1040</width> - <z>1</z> - <height>160</height> - <location_x>680</location_x> - <location_y>0</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.RadioLogger - <plugin_config> - <split>150</split> - <formatted_time /> - <showdups>false</showdups> - <hidenodests>false</hidenodests> - <analyzers name="6lowpan-pcap" /> - </plugin_config> - <width>500</width> - <z>0</z> - <height>300</height> - <location_x>290</location_x> - <location_y>422</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.ScriptRunner - <plugin_config> - <scriptfile>[CONTIKI_DIR]/tests/16-6tisch/js/unit-test.js</scriptfile> - <active>true</active> - </plugin_config> - <width>495</width> - <z>0</z> - <height>525</height> - <location_x>663</location_x> - <location_y>105</location_y> - </plugin> -</simconf> - diff --git a/tests/16-6tisch/Makefile b/tests/16-6tisch/Makefile deleted file mode 100644 index 272bc7da157d96c1a0640317971c1897e31a9f1a..0000000000000000000000000000000000000000 --- a/tests/16-6tisch/Makefile +++ /dev/null @@ -1 +0,0 @@ -include ../Makefile.simulation-test diff --git a/tests/17-tun-rpl-br/01-border-router-cooja.csc b/tests/17-tun-rpl-br/01-border-router-cooja.csc new file mode 100644 index 0000000000000000000000000000000000000000..b0d95600a9c2b9e29f00492edb06c97269f79c05 --- /dev/null +++ b/tests/17-tun-rpl-br/01-border-router-cooja.csc @@ -0,0 +1,252 @@ +<?xml version="1.0" encoding="UTF-8"?> +<simconf> + <project EXPORT="discard">[APPS_DIR]/mrm</project> + <project EXPORT="discard">[APPS_DIR]/mspsim</project> + <project EXPORT="discard">[APPS_DIR]/avrora</project> + <project EXPORT="discard">[APPS_DIR]/serial_socket</project> + <project EXPORT="discard">[APPS_DIR]/powertracker</project> + <simulation> + <title>My simulation</title> + <speedlimit>1.0</speedlimit> + <randomseed>123456</randomseed> + <motedelay_us>1000000</motedelay_us> + <radiomedium> + org.contikios.cooja.radiomediums.UDGM + <transmitting_range>50.0</transmitting_range> + <interference_range>100.0</interference_range> + <success_ratio_tx>1.0</success_ratio_tx> + <success_ratio_rx>1.0</success_ratio_rx> + </radiomedium> + <events> + <logoutput>40000</logoutput> + </events> + <motetype> + org.contikios.cooja.contikimote.ContikiMoteType + <identifier>mtype295</identifier> + <description>Cooja Mote Type #1</description> + <source>[CONTIKI_DIR]/examples/rpl-border-router/border-router.c</source> + <commands>make TARGET=cooja clean +make -j border-router.cooja TARGET=cooja</commands> + <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> + <symbols>false</symbols> + </motetype> + <motetype> + org.contikios.cooja.contikimote.ContikiMoteType + <identifier>mtype686</identifier> + <description>Cooja Mote Type #2</description> + <source>[CONTIKI_DIR]/examples/hello-world/hello-world.c</source> + <commands>make TARGET=cooja clean +make -j hello-world.cooja TARGET=cooja</commands> + <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> + <symbols>false</symbols> + </motetype> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>54.36775767371176</x> + <y>24.409055040864118</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>1</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> + </interface_config> + <motetype_identifier>mtype295</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>83.54989222799365</x> + <y>52.63050856506214</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>2</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> + </interface_config> + <motetype_identifier>mtype686</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>108.91767775240822</x> + <y>78.59778809170032</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>3</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> + </interface_config> + <motetype_identifier>mtype686</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>139.91021061864723</x> + <y>98.34190023350419</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>4</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> + </interface_config> + <motetype_identifier>mtype686</motetype_identifier> + </mote> + </simulation> + <plugin> + org.contikios.cooja.plugins.SimControl + <width>280</width> + <z>1</z> + <height>160</height> + <location_x>400</location_x> + <location_y>0</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.Visualizer + <plugin_config> + <moterelations>true</moterelations> + <skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin> + <skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin> + <viewport>1.9798610460263038 0.0 0.0 1.9798610460263038 -61.112037797038525 -1.2848438586294648</viewport> + </plugin_config> + <width>400</width> + <z>4</z> + <height>400</height> + <location_x>1</location_x> + <location_y>1</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.LogListener + <plugin_config> + <filter>ID:4</filter> + <formatted_time /> + <coloring /> + </plugin_config> + <width>1404</width> + <z>2</z> + <height>240</height> + <location_x>400</location_x> + <location_y>160</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.TimeLine + <plugin_config> + <mote>0</mote> + <mote>1</mote> + <mote>2</mote> + <mote>3</mote> + <showRadioRXTX /> + <showRadioHW /> + <showLEDs /> + <zoomfactor>500.0</zoomfactor> + </plugin_config> + <width>1804</width> + <z>6</z> + <height>166</height> + <location_x>0</location_x> + <location_y>753</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.Notes + <plugin_config> + <notes>Enter notes here</notes> + <decorations>true</decorations> + </plugin_config> + <width>1124</width> + <z>5</z> + <height>160</height> + <location_x>680</location_x> + <location_y>0</location_y> + </plugin> + <plugin> + org.contikios.cooja.serialsocket.SerialSocketServer + <mote_arg>0</mote_arg> + <plugin_config> + <port>60001</port> + <bound>true</bound> + </plugin_config> + <width>362</width> + <z>3</z> + <height>116</height> + <location_x>13</location_x> + <location_y>414</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.ScriptRunner + <plugin_config> + <script>TIMEOUT(10000000000); /* milliseconds. no action at timeout */ +/* Set simulaion speed to real time */ +sim.setSpeedLimit(1.0);</script> + <active>true</active> + </plugin_config> + <width>600</width> + <z>0</z> + <height>700</height> + <location_x>1037</location_x> + <location_y>40</location_y> + </plugin> +</simconf> diff --git a/tests/17-tun-rpl-br/01-border-router-cooja.sh b/tests/17-tun-rpl-br/01-border-router-cooja.sh new file mode 100755 index 0000000000000000000000000000000000000000..11b2edc8a52bc079bc57b96cc5825c3640e85fa4 --- /dev/null +++ b/tests/17-tun-rpl-br/01-border-router-cooja.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 + +# Simulation file +BASENAME=01-border-router-cooja + +bash test-border-router.sh $CONTIKI $BASENAME fd00::204:4:4:4 60 diff --git a/tests/17-tun-rpl-br/02-border-router-cooja-tsch.csc b/tests/17-tun-rpl-br/02-border-router-cooja-tsch.csc new file mode 100644 index 0000000000000000000000000000000000000000..61a6c96ced82617732c4d014af7ccafedcd794ac --- /dev/null +++ b/tests/17-tun-rpl-br/02-border-router-cooja-tsch.csc @@ -0,0 +1,252 @@ +<?xml version="1.0" encoding="UTF-8"?> +<simconf> + <project EXPORT="discard">[APPS_DIR]/mrm</project> + <project EXPORT="discard">[APPS_DIR]/mspsim</project> + <project EXPORT="discard">[APPS_DIR]/avrora</project> + <project EXPORT="discard">[APPS_DIR]/serial_socket</project> + <project EXPORT="discard">[APPS_DIR]/powertracker</project> + <simulation> + <title>My simulation</title> + <speedlimit>1.0</speedlimit> + <randomseed>123456</randomseed> + <motedelay_us>1000000</motedelay_us> + <radiomedium> + org.contikios.cooja.radiomediums.UDGM + <transmitting_range>50.0</transmitting_range> + <interference_range>100.0</interference_range> + <success_ratio_tx>1.0</success_ratio_tx> + <success_ratio_rx>1.0</success_ratio_rx> + </radiomedium> + <events> + <logoutput>40000</logoutput> + </events> + <motetype> + org.contikios.cooja.contikimote.ContikiMoteType + <identifier>mtype295</identifier> + <description>Cooja Mote Type #1</description> + <source>[CONTIKI_DIR]/examples/rpl-border-router/border-router.c</source> + <commands>make TARGET=cooja clean +make -j border-router.cooja TARGET=cooja MAKE_MAC=MAKE_MAC_TSCH</commands> + <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> + <symbols>false</symbols> + </motetype> + <motetype> + org.contikios.cooja.contikimote.ContikiMoteType + <identifier>mtype686</identifier> + <description>Cooja Mote Type #2</description> + <source>[CONTIKI_DIR]/examples/hello-world/hello-world.c</source> + <commands>make TARGET=cooja clean +make -j hello-world.cooja TARGET=cooja MAKE_MAC=MAKE_MAC_TSCH</commands> + <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> + <symbols>false</symbols> + </motetype> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>54.36775767371176</x> + <y>24.409055040864118</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>1</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> + </interface_config> + <motetype_identifier>mtype295</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>83.54989222799365</x> + <y>52.63050856506214</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>2</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> + </interface_config> + <motetype_identifier>mtype686</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>108.91767775240822</x> + <y>78.59778809170032</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>3</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> + </interface_config> + <motetype_identifier>mtype686</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>139.91021061864723</x> + <y>98.34190023350419</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>4</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> + </interface_config> + <motetype_identifier>mtype686</motetype_identifier> + </mote> + </simulation> + <plugin> + org.contikios.cooja.plugins.SimControl + <width>280</width> + <z>1</z> + <height>160</height> + <location_x>400</location_x> + <location_y>0</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.Visualizer + <plugin_config> + <moterelations>true</moterelations> + <skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin> + <skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin> + <viewport>1.9798610460263038 0.0 0.0 1.9798610460263038 -61.112037797038525 -1.2848438586294648</viewport> + </plugin_config> + <width>400</width> + <z>4</z> + <height>400</height> + <location_x>1</location_x> + <location_y>1</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.LogListener + <plugin_config> + <filter>ID:4</filter> + <formatted_time /> + <coloring /> + </plugin_config> + <width>1404</width> + <z>2</z> + <height>240</height> + <location_x>400</location_x> + <location_y>160</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.TimeLine + <plugin_config> + <mote>0</mote> + <mote>1</mote> + <mote>2</mote> + <mote>3</mote> + <showRadioRXTX /> + <showRadioHW /> + <showLEDs /> + <zoomfactor>500.0</zoomfactor> + </plugin_config> + <width>1804</width> + <z>6</z> + <height>166</height> + <location_x>0</location_x> + <location_y>753</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.Notes + <plugin_config> + <notes>Enter notes here</notes> + <decorations>true</decorations> + </plugin_config> + <width>1124</width> + <z>5</z> + <height>160</height> + <location_x>680</location_x> + <location_y>0</location_y> + </plugin> + <plugin> + org.contikios.cooja.serialsocket.SerialSocketServer + <mote_arg>0</mote_arg> + <plugin_config> + <port>60001</port> + <bound>true</bound> + </plugin_config> + <width>362</width> + <z>3</z> + <height>116</height> + <location_x>13</location_x> + <location_y>414</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.ScriptRunner + <plugin_config> + <script>TIMEOUT(10000000000); /* milliseconds. no action at timeout */ +/* Set simulaion speed to real time */ +sim.setSpeedLimit(1.0);</script> + <active>true</active> + </plugin_config> + <width>600</width> + <z>0</z> + <height>700</height> + <location_x>1037</location_x> + <location_y>40</location_y> + </plugin> +</simconf> diff --git a/tests/17-tun-rpl-br/02-border-router-cooja-tsch.sh b/tests/17-tun-rpl-br/02-border-router-cooja-tsch.sh new file mode 100755 index 0000000000000000000000000000000000000000..c7e61c8a7121997b40df85d37db0c0cbe4f83181 --- /dev/null +++ b/tests/17-tun-rpl-br/02-border-router-cooja-tsch.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 + +# Simulation file +BASENAME=02-border-router-cooja-tsch + +# Add a little extra initial time to account for TSCH association time +bash test-border-router.sh $CONTIKI $BASENAME fd00::204:4:4:4 120 diff --git a/examples/coap/server-only.csc b/tests/17-tun-rpl-br/03-border-router-sky.csc similarity index 59% rename from examples/coap/server-only.csc rename to tests/17-tun-rpl-br/03-border-router-sky.csc index 715deae1c192536da44e82a4195af9de10154bdd..e19573d8dd8c7220620ef6f5b128c579294874df 100644 --- a/examples/coap/server-only.csc +++ b/tests/17-tun-rpl-br/03-border-router-sky.csc @@ -4,17 +4,16 @@ <project EXPORT="discard">[APPS_DIR]/mspsim</project> <project EXPORT="discard">[APPS_DIR]/avrora</project> <project EXPORT="discard">[APPS_DIR]/serial_socket</project> - <project EXPORT="discard">[APPS_DIR]/collect-view</project> <project EXPORT="discard">[APPS_DIR]/powertracker</project> <simulation> - <title>REST with RPL router</title> + <title>My simulation</title> <speedlimit>1.0</speedlimit> <randomseed>123456</randomseed> <motedelay_us>1000000</motedelay_us> <radiomedium> org.contikios.cooja.radiomediums.UDGM <transmitting_range>50.0</transmitting_range> - <interference_range>50.0</interference_range> + <interference_range>100.0</interference_range> <success_ratio_tx>1.0</success_ratio_tx> <success_ratio_rx>1.0</success_ratio_rx> </radiomedium> @@ -23,10 +22,11 @@ </events> <motetype> org.contikios.cooja.mspmote.SkyMoteType - <identifier>rplroot</identifier> - <description>Sky RPL Root</description> + <identifier>sky1</identifier> + <description>Sky Mote Type #sky1</description> <source EXPORT="discard">[CONTIKI_DIR]/examples/rpl-border-router/border-router.c</source> - <commands EXPORT="discard">make border-router.sky TARGET=sky</commands> + <commands EXPORT="discard">make clean TARGET=sky +make -j border-router.sky TARGET=sky</commands> <firmware EXPORT="copy">[CONTIKI_DIR]/examples/rpl-border-router/border-router.sky</firmware> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> @@ -46,11 +46,12 @@ </motetype> <motetype> org.contikios.cooja.mspmote.SkyMoteType - <identifier>server</identifier> - <description>Erbium Server</description> - <source EXPORT="discard">[CONTIKI_DIR]/examples/coap/coap-example-server.c</source> - <commands EXPORT="discard">make coap-example-server.sky TARGET=sky</commands> - <firmware EXPORT="copy">[CONTIKI_DIR]/examples/coap/coap-example-server.sky</firmware> + <identifier>sky2</identifier> + <description>Sky Mote Type #sky2</description> + <source EXPORT="discard">[CONTIKI_DIR]/examples/hello-world/hello-world.c</source> + <commands EXPORT="discard">make clean TARGET=sky +make -j hello-world.sky TARGET=sky</commands> + <firmware EXPORT="copy">[CONTIKI_DIR]/examples/hello-world/hello-world.sky</firmware> <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> <moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface> @@ -71,55 +72,96 @@ <breakpoints /> <interface_config> org.contikios.cooja.interfaces.Position - <x>33.260163187353555</x> - <y>30.643217359962595</y> + <x>-24.750327773354453</x> + <y>17.688901393447438</y> <z>0.0</z> </interface_config> + <interface_config> + org.contikios.cooja.mspmote.interfaces.MspClock + <deviation>1.0</deviation> + </interface_config> <interface_config> org.contikios.cooja.mspmote.interfaces.MspMoteID <id>1</id> </interface_config> - <motetype_identifier>rplroot</motetype_identifier> + <motetype_identifier>sky1</motetype_identifier> </mote> <mote> <breakpoints /> <interface_config> org.contikios.cooja.interfaces.Position - <x>35.100895239785295</x> - <y>39.70574552287428</y> + <x>1.091493067677618</x> + <y>40.943504236660225</y> <z>0.0</z> </interface_config> + <interface_config> + org.contikios.cooja.mspmote.interfaces.MspClock + <deviation>1.0</deviation> + </interface_config> <interface_config> org.contikios.cooja.mspmote.interfaces.MspMoteID <id>2</id> </interface_config> - <motetype_identifier>server</motetype_identifier> + <motetype_identifier>sky2</motetype_identifier> + </mote> + <mote> + <breakpoints /> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>22.647678967805337</x> + <y>61.6365018442491</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.mspmote.interfaces.MspClock + <deviation>1.0</deviation> + </interface_config> + <interface_config> + org.contikios.cooja.mspmote.interfaces.MspMoteID + <id>3</id> + </interface_config> + <motetype_identifier>sky2</motetype_identifier> + </mote> + <mote> + <breakpoints /> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>44.02005813888037</x> + <y>93.02398317771755</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.mspmote.interfaces.MspClock + <deviation>1.0</deviation> + </interface_config> + <interface_config> + org.contikios.cooja.mspmote.interfaces.MspMoteID + <id>4</id> + </interface_config> + <motetype_identifier>sky2</motetype_identifier> </mote> </simulation> <plugin> org.contikios.cooja.plugins.SimControl - <width>259</width> - <z>0</z> - <height>179</height> - <location_x>2</location_x> - <location_y>1</location_y> + <width>280</width> + <z>1</z> + <height>160</height> + <location_x>400</location_x> + <location_y>0</location_y> </plugin> <plugin> org.contikios.cooja.plugins.Visualizer <plugin_config> + <moterelations>true</moterelations> <skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin> <skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.AttributeVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.LEDVisualizerSkin</skin> - <skin>org.contikios.cooja.plugins.skins.AddressVisualizerSkin</skin> - <viewport>7.9849281638410705 0.0 0.0 7.9849281638410705 -133.27812697619663 -225.04752569190535</viewport> + <viewport>2.3610941331949244 0.0 0.0 2.3610941331949244 119.38219749746548 -4.52452305190821</viewport> </plugin_config> - <width>300</width> - <z>1</z> - <height>175</height> - <location_x>262</location_x> - <location_y>2</location_y> + <width>400</width> + <z>3</z> + <height>400</height> + <location_x>1</location_x> + <location_y>1</location_y> </plugin> <plugin> org.contikios.cooja.plugins.LogListener @@ -128,66 +170,67 @@ <formatted_time /> <coloring /> </plugin_config> - <width>560</width> - <z>3</z> - <height>326</height> - <location_x>1</location_x> - <location_y>293</location_y> - </plugin> - <plugin> - org.contikios.cooja.plugins.RadioLogger - <plugin_config> - <split>150</split> - <formatted_time /> - <showdups>false</showdups> - <hidenodests>false</hidenodests> - <analyzers name="6lowpan" /> - </plugin_config> - <width>451</width> - <z>-1</z> - <height>305</height> - <location_x>73</location_x> - <location_y>140</location_y> - <minimized>true</minimized> - </plugin> - <plugin> - org.contikios.cooja.serialsocket.SerialSocketServer - <mote_arg>0</mote_arg> - <width>422</width> - <z>4</z> - <height>74</height> - <location_x>39</location_x> - <location_y>199</location_y> + <width>1404</width> + <z>6</z> + <height>240</height> + <location_x>400</location_x> + <location_y>160</location_y> </plugin> <plugin> org.contikios.cooja.plugins.TimeLine <plugin_config> <mote>0</mote> <mote>1</mote> + <mote>2</mote> + <mote>3</mote> <showRadioRXTX /> <showRadioHW /> <showLEDs /> - <showWatchpoints /> - <zoomfactor>25.49079397896416</zoomfactor> + <zoomfactor>500.0</zoomfactor> </plugin_config> - <width>1624</width> + <width>1804</width> <z>5</z> - <height>252</height> - <location_x>4</location_x> - <location_y>622</location_y> + <height>166</height> + <location_x>0</location_x> + <location_y>742</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.Notes + <plugin_config> + <notes>Enter notes here</notes> + <decorations>true</decorations> + </plugin_config> + <width>1124</width> + <z>4</z> + <height>160</height> + <location_x>680</location_x> + <location_y>0</location_y> </plugin> <plugin> - org.contikios.cooja.plugins.MoteInterfaceViewer - <mote_arg>1</mote_arg> + org.contikios.cooja.serialsocket.SerialSocketServer + <mote_arg>0</mote_arg> <plugin_config> - <interface>Serial port</interface> - <scrollpos>0,0</scrollpos> + <port>60001</port> + <bound>true</bound> </plugin_config> - <width>702</width> + <width>362</width> <z>2</z> - <height>646</height> - <location_x>564</location_x> - <location_y>2</location_y> + <height>116</height> + <location_x>30</location_x> + <location_y>403</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.ScriptRunner + <plugin_config> + <script>TIMEOUT(10000000000); /* milliseconds. no action at timeout */ +/* Set simulaion speed to real time */ +sim.setSpeedLimit(1.0);</script> + <active>true</active> + </plugin_config> + <width>600</width> + <z>0</z> + <height>700</height> + <location_x>850</location_x> + <location_y>13</location_y> </plugin> </simconf> - diff --git a/tests/17-tun-rpl-br/03-border-router-sky.sh b/tests/17-tun-rpl-br/03-border-router-sky.sh new file mode 100755 index 0000000000000000000000000000000000000000..7ffa4265e25c907e8a0b65e2503cc737b335727d --- /dev/null +++ b/tests/17-tun-rpl-br/03-border-router-sky.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 + +# Simulation file +BASENAME=03-border-router-sky + +bash test-border-router.sh $CONTIKI $BASENAME fd00::0212:7404:0004:0404 60 diff --git a/tests/17-tun-rpl-br/04-border-router-traceroute.csc b/tests/17-tun-rpl-br/04-border-router-traceroute.csc new file mode 100644 index 0000000000000000000000000000000000000000..b0d95600a9c2b9e29f00492edb06c97269f79c05 --- /dev/null +++ b/tests/17-tun-rpl-br/04-border-router-traceroute.csc @@ -0,0 +1,252 @@ +<?xml version="1.0" encoding="UTF-8"?> +<simconf> + <project EXPORT="discard">[APPS_DIR]/mrm</project> + <project EXPORT="discard">[APPS_DIR]/mspsim</project> + <project EXPORT="discard">[APPS_DIR]/avrora</project> + <project EXPORT="discard">[APPS_DIR]/serial_socket</project> + <project EXPORT="discard">[APPS_DIR]/powertracker</project> + <simulation> + <title>My simulation</title> + <speedlimit>1.0</speedlimit> + <randomseed>123456</randomseed> + <motedelay_us>1000000</motedelay_us> + <radiomedium> + org.contikios.cooja.radiomediums.UDGM + <transmitting_range>50.0</transmitting_range> + <interference_range>100.0</interference_range> + <success_ratio_tx>1.0</success_ratio_tx> + <success_ratio_rx>1.0</success_ratio_rx> + </radiomedium> + <events> + <logoutput>40000</logoutput> + </events> + <motetype> + org.contikios.cooja.contikimote.ContikiMoteType + <identifier>mtype295</identifier> + <description>Cooja Mote Type #1</description> + <source>[CONTIKI_DIR]/examples/rpl-border-router/border-router.c</source> + <commands>make TARGET=cooja clean +make -j border-router.cooja TARGET=cooja</commands> + <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> + <symbols>false</symbols> + </motetype> + <motetype> + org.contikios.cooja.contikimote.ContikiMoteType + <identifier>mtype686</identifier> + <description>Cooja Mote Type #2</description> + <source>[CONTIKI_DIR]/examples/hello-world/hello-world.c</source> + <commands>make TARGET=cooja clean +make -j hello-world.cooja TARGET=cooja</commands> + <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> + <symbols>false</symbols> + </motetype> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>54.36775767371176</x> + <y>24.409055040864118</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>1</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> + </interface_config> + <motetype_identifier>mtype295</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>83.54989222799365</x> + <y>52.63050856506214</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>2</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> + </interface_config> + <motetype_identifier>mtype686</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>108.91767775240822</x> + <y>78.59778809170032</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>3</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> + </interface_config> + <motetype_identifier>mtype686</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>139.91021061864723</x> + <y>98.34190023350419</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>4</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> + </interface_config> + <motetype_identifier>mtype686</motetype_identifier> + </mote> + </simulation> + <plugin> + org.contikios.cooja.plugins.SimControl + <width>280</width> + <z>1</z> + <height>160</height> + <location_x>400</location_x> + <location_y>0</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.Visualizer + <plugin_config> + <moterelations>true</moterelations> + <skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin> + <skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin> + <viewport>1.9798610460263038 0.0 0.0 1.9798610460263038 -61.112037797038525 -1.2848438586294648</viewport> + </plugin_config> + <width>400</width> + <z>4</z> + <height>400</height> + <location_x>1</location_x> + <location_y>1</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.LogListener + <plugin_config> + <filter>ID:4</filter> + <formatted_time /> + <coloring /> + </plugin_config> + <width>1404</width> + <z>2</z> + <height>240</height> + <location_x>400</location_x> + <location_y>160</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.TimeLine + <plugin_config> + <mote>0</mote> + <mote>1</mote> + <mote>2</mote> + <mote>3</mote> + <showRadioRXTX /> + <showRadioHW /> + <showLEDs /> + <zoomfactor>500.0</zoomfactor> + </plugin_config> + <width>1804</width> + <z>6</z> + <height>166</height> + <location_x>0</location_x> + <location_y>753</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.Notes + <plugin_config> + <notes>Enter notes here</notes> + <decorations>true</decorations> + </plugin_config> + <width>1124</width> + <z>5</z> + <height>160</height> + <location_x>680</location_x> + <location_y>0</location_y> + </plugin> + <plugin> + org.contikios.cooja.serialsocket.SerialSocketServer + <mote_arg>0</mote_arg> + <plugin_config> + <port>60001</port> + <bound>true</bound> + </plugin_config> + <width>362</width> + <z>3</z> + <height>116</height> + <location_x>13</location_x> + <location_y>414</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.ScriptRunner + <plugin_config> + <script>TIMEOUT(10000000000); /* milliseconds. no action at timeout */ +/* Set simulaion speed to real time */ +sim.setSpeedLimit(1.0);</script> + <active>true</active> + </plugin_config> + <width>600</width> + <z>0</z> + <height>700</height> + <location_x>1037</location_x> + <location_y>40</location_y> + </plugin> +</simconf> diff --git a/tests/17-tun-rpl-br/04-border-router-traceroute.sh b/tests/17-tun-rpl-br/04-border-router-traceroute.sh new file mode 100755 index 0000000000000000000000000000000000000000..e1e9d6cdd2e4810d3364e2372578db7020116a01 --- /dev/null +++ b/tests/17-tun-rpl-br/04-border-router-traceroute.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 + +# Simulation file +BASENAME=04-border-router-traceroute + +# Destination IPv6 +IPADDR=fd00::204:4:4:4 + +# Time allocated for toplogy formation +WAIT_TIME=60 + +# The expected hop count +TARGETHOPS=4 + +# Start simulation +echo "Starting Cooja simulation $BASENAME.csc" +java -Xshare:on -jar $CONTIKI/tools/cooja/dist/cooja.jar -nogui=$BASENAME.csc -contiki=$CONTIKI > $BASENAME.coojalog & +JPID=$! +sleep 20 + +# Connect to the simlation +echo "Starting tunslip6" +make -C $CONTIKI/tools tunslip6 +make -C $CONTIKI/examples/rpl-border-router/ connect-router-cooja TARGET=zoul >> $BASENAME.tunslip.log 2>&1 & +MPID=$! +printf "Waiting for network formation (%d seconds)\n" "$WAIT_TIME" +sleep $WAIT_TIME + +# Do ping +echo "Running Traceroute" +traceroute6 $IPADDR -m 5 | tee $BASENAME.scriptlog +# Fetch traceroute6 status code (not $? because this is piped) +STATUS=${PIPESTATUS[0]} +HOPS=`wc $BASENAME.scriptlog -l | cut -f 1 -d ' '` + +echo "Closing simulation and tunslip6" +sleep 1 +kill -9 $JPID +kill -9 $MPID +sleep 1 +rm COOJA.testlog +rm COOJA.log + +if [ $STATUS -eq 0 ] && [ $HOPS -eq $TARGETHOPS ] ; then + printf "%-32s TEST OK\n" "$BASENAME" | tee $BASENAME.testlog; +else + echo "==== $BASENAME.coojalog ====" ; cat $BASENAME.coojalog; + echo "==== $BASENAME.tunslip.log ====" ; cat $BASENAME.tunslip.log; + echo "==== $BASENAME.scriptlog ====" ; cat $BASENAME.scriptlog; + + printf "%-32s TEST FAIL\n" "$BASENAME" | tee $BASENAME.testlog; +fi + +# We do not want Make to stop -> Return 0 +# The Makefile will check if a log contains FAIL at the end + +exit 0 diff --git a/tests/17-tun-rpl-br/05-native-ping.sh b/tests/17-tun-rpl-br/05-native-ping.sh new file mode 100755 index 0000000000000000000000000000000000000000..9e677c16e609af328e804c57a5ae2015915b2007 --- /dev/null +++ b/tests/17-tun-rpl-br/05-native-ping.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 +# Test basename +BASENAME=01-native-ping + +IPADDR=fd00::302:304:506:708 + +# Starting Contiki-NG native node +echo "Starting native node" +make -C $CONTIKI/examples/hello-world > make.log 2> make.err +sudo $CONTIKI/examples/hello-world/hello-world.native > node.log 2> node.err & +CPID=$! +sleep 2 + +# Do ping +echo "Pinging" +ping6 $IPADDR -c 5 | tee $BASENAME.log +# Fetch ping6 status code (not $? because this is piped) +STATUS=${PIPESTATUS[0]} + +echo "Closing native node" +sleep 2 +pgrep hello-world | sudo xargs kill -9 + +if [ $STATUS -eq 0 ] ; then + cp $BASENAME.log $BASENAME.testlog + printf "%-32s TEST OK\n" "$BASENAME" | tee $BASENAME.testlog; +else + echo "==== make.log ====" ; cat make.log; + echo "==== make.err ====" ; cat make.err; + echo "==== node.log ====" ; cat node.log; + echo "==== node.err ====" ; cat node.err; + echo "==== $BASENAME.log ====" ; cat $BASENAME.log; + + printf "%-32s TEST FAIL\n" "$BASENAME" | tee $BASENAME.testlog; +fi + +rm make.log +rm make.err +rm node.log +rm node.err + +# We do not want Make to stop -> Return 0 +# The Makefile will check if a log contains FAIL at the end +exit 0 diff --git a/tests/17-tun-rpl-br/06-native-coap.sh b/tests/17-tun-rpl-br/06-native-coap.sh new file mode 100755 index 0000000000000000000000000000000000000000..88627ec19c2b2074f3d05d98ab0617d248ceadff --- /dev/null +++ b/tests/17-tun-rpl-br/06-native-coap.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 +# Test basename +BASENAME=06-native-coap + +IPADDR=fd00::302:304:506:708 + +declare -i OKCOUNT=0 +declare -i TESTCOUNT=0 + +# Starting Contiki-NG native node +echo "Starting native CoAP server" +make -C $CONTIKI/examples/coap/coap-example-server > make.log 2> make.err +sudo $CONTIKI/examples/coap/coap-example-server/coap-example-server.native > node.log 2> node.err & +CPID=$! +sleep 2 + +# Send CoAP requests +echo "Sending CoAP requests" + +rm -f $BASENAME.log +for TARGET in .well-known/core test/push; do + echo "Get $TARGET" | tee -a $BASENAME.log + coap get coap://[$IPADDR]/$TARGET 2>&1 | tee coap.log + cat coap.log >> $BASENAME.log + # Fetch coap status code (not $? because this is piped) + SUCCESS=`grep -c '(2.05)' coap.log` + if [ $SUCCESS == 1 ]; then + printf "> OK\n" + OKCOUNT+=1 + else + printf "> FAIL\n" + fi + TESTCOUNT+=1 +done + +echo "Closing native node" +sleep 2 +pgrep coap-example | sudo xargs kill -9 + +if [ $TESTCOUNT -eq $OKCOUNT ] ; then + printf "%-32s TEST OK %3d/%d\n" "$BASENAME" "$OKCOUNT" "$TESTCOUNT" | tee $BASENAME.testlog; +else + echo "==== make.log ====" ; cat make.log; + echo "==== make.err ====" ; cat make.err; + echo "==== node.log ====" ; cat node.log; + echo "==== node.err ====" ; cat node.err; + echo "==== $BASENAME.log ====" ; cat $BASENAME.log; + + printf "%-32s TEST FAIL %3d/%d\n" "$BASENAME" "$OKCOUNT" "$TESTCOUNT" | tee $BASENAME.testlog; +fi + +rm -f make.log make.err node.log node.err coap.log + +# We do not want Make to stop -> Return 0 +# The Makefile will check if a log contains FAIL at the end +exit 0 diff --git a/tests/17-tun-rpl-br/07-native-border-router-cooja.csc b/tests/17-tun-rpl-br/07-native-border-router-cooja.csc new file mode 100644 index 0000000000000000000000000000000000000000..7140d183cae72e78eb3498d0faa0212f3160f78a --- /dev/null +++ b/tests/17-tun-rpl-br/07-native-border-router-cooja.csc @@ -0,0 +1,254 @@ +<?xml version="1.0" encoding="UTF-8"?> +<simconf> + <project EXPORT="discard">[APPS_DIR]/mrm</project> + <project EXPORT="discard">[APPS_DIR]/mspsim</project> + <project EXPORT="discard">[APPS_DIR]/avrora</project> + <project EXPORT="discard">[APPS_DIR]/serial_socket</project> + <project EXPORT="discard">[APPS_DIR]/powertracker</project> + <simulation> + <title>My simulation</title> + <speedlimit>1.0</speedlimit> + <randomseed>123456</randomseed> + <motedelay_us>1000000</motedelay_us> + <radiomedium> + org.contikios.cooja.radiomediums.UDGM + <transmitting_range>50.0</transmitting_range> + <interference_range>100.0</interference_range> + <success_ratio_tx>1.0</success_ratio_tx> + <success_ratio_rx>1.0</success_ratio_rx> + </radiomedium> + <events> + <logoutput>40000</logoutput> + </events> + <motetype> + org.contikios.cooja.contikimote.ContikiMoteType + <identifier>mtype295</identifier> + <description>Cooja Mote Type #1</description> + <source>[CONTIKI_DIR]/examples/slip-radio/slip-radio.c</source> + <commands>make TARGET=cooja clean +make -j slip-radio.cooja TARGET=cooja</commands> + <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> + <symbols>false</symbols> + </motetype> + <motetype> + org.contikios.cooja.contikimote.ContikiMoteType + <identifier>mtype686</identifier> + <description>Cooja Mote Type #2</description> + <source>[CONTIKI_DIR]/examples/hello-world/hello-world.c</source> + <commands>make TARGET=cooja clean +make -j hello-world.cooja TARGET=cooja</commands> + <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface> + <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface> + <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface> + <symbols>false</symbols> + </motetype> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>54.36775767371176</x> + <y>24.409055040864118</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>1</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> + </interface_config> + <motetype_identifier>mtype295</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>83.54989222799365</x> + <y>52.63050856506214</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>2</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> + </interface_config> + <motetype_identifier>mtype686</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>108.91767775240822</x> + <y>78.59778809170032</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>3</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> + </interface_config> + <motetype_identifier>mtype686</motetype_identifier> + </mote> + <mote> + <interface_config> + org.contikios.cooja.interfaces.Position + <x>139.91021061864723</x> + <y>98.34190023350419</y> + <z>0.0</z> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + <id>4</id> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiRadio + <bitrate>250.0</bitrate> + </interface_config> + <interface_config> + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom> + </interface_config> + <motetype_identifier>mtype686</motetype_identifier> + </mote> + </simulation> + <plugin> + org.contikios.cooja.plugins.SimControl + <width>280</width> + <z>1</z> + <height>160</height> + <location_x>400</location_x> + <location_y>0</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.Visualizer + <plugin_config> + <moterelations>true</moterelations> + <skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin> + <skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin> + <viewport>1.9798610460263038 0.0 0.0 1.9798610460263038 -61.112037797038525 -1.2848438586294648</viewport> + </plugin_config> + <width>400</width> + <z>4</z> + <height>400</height> + <location_x>1</location_x> + <location_y>1</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.LogListener + <plugin_config> + <filter>ID:4</filter> + <formatted_time /> + <coloring /> + </plugin_config> + <width>1404</width> + <z>2</z> + <height>240</height> + <location_x>400</location_x> + <location_y>160</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.TimeLine + <plugin_config> + <mote>0</mote> + <mote>1</mote> + <mote>2</mote> + <mote>3</mote> + <showRadioRXTX /> + <showRadioHW /> + <showLEDs /> + <zoomfactor>500.0</zoomfactor> + </plugin_config> + <width>1804</width> + <z>6</z> + <height>166</height> + <location_x>0</location_x> + <location_y>753</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.Notes + <plugin_config> + <notes>Enter notes here</notes> + <decorations>true</decorations> + </plugin_config> + <width>1124</width> + <z>5</z> + <height>160</height> + <location_x>680</location_x> + <location_y>0</location_y> + </plugin> + <plugin> + org.contikios.cooja.serialsocket.SerialSocketServer + <mote_arg>0</mote_arg> + <plugin_config> + <port>60001</port> + <bound>true</bound> + </plugin_config> + <width>362</width> + <z>3</z> + <height>116</height> + <location_x>13</location_x> + <location_y>414</location_y> + </plugin> + <plugin> + org.contikios.cooja.plugins.ScriptRunner + <plugin_config> + <script>TIMEOUT(10000000000); /* milliseconds. no action at timeout */ +/* Set simulaion speed to real time. Required for + * Native BR test, as the Native BR will run as a + * unix process, at real time. */ +sim.setSpeedLimit(1.0);</script> + <active>true</active> + </plugin_config> + <width>600</width> + <z>0</z> + <height>700</height> + <location_x>1037</location_x> + <location_y>40</location_y> + </plugin> +</simconf> diff --git a/tests/17-tun-rpl-br/07-native-border-router-cooja.sh b/tests/17-tun-rpl-br/07-native-border-router-cooja.sh new file mode 100755 index 0000000000000000000000000000000000000000..8f91bd726b45c663fc8170c90b7fb30de6545964 --- /dev/null +++ b/tests/17-tun-rpl-br/07-native-border-router-cooja.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 + +# Simulation file +BASENAME=07-native-border-router-cooja + +bash test-native-border-router.sh $CONTIKI $BASENAME fd00::204:4:4:4 60 diff --git a/tests/17-tun-rpl-br/Makefile b/tests/17-tun-rpl-br/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c46e5271d5a3d2374a99b4d70b09ac5e8870495b --- /dev/null +++ b/tests/17-tun-rpl-br/Makefile @@ -0,0 +1 @@ +include ../Makefile.script-test diff --git a/tests/17-tun-rpl-br/test-border-router.sh b/tests/17-tun-rpl-br/test-border-router.sh new file mode 100755 index 0000000000000000000000000000000000000000..6bfb8cf627e6661112caa755ee3ff7c245179c6b --- /dev/null +++ b/tests/17-tun-rpl-br/test-border-router.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 + +# Simulation file +BASENAME=$2 + +# Destination IPv6 +IPADDR=$3 + +# Time allocated for convergence +WAIT_TIME=$4 + +# ICMP request-reply count +COUNT=5 + +# Start simulation +echo "Starting Cooja simulation $BASENAME.csc" +java -Xshare:on -jar $CONTIKI/tools/cooja/dist/cooja.jar -nogui=$BASENAME.csc -contiki=$CONTIKI > $BASENAME.coojalog & +JPID=$! +sleep 20 + +# Connect to the simlation +echo "Starting tunslip6" +make -C $CONTIKI/tools tunslip6 +make -C $CONTIKI/examples/rpl-border-router/ connect-router-cooja TARGET=zoul >> $BASENAME.tunslip.log 2>&1 & +MPID=$! +printf "Waiting for network formation (%d seconds)\n" "$WAIT_TIME" +sleep $WAIT_TIME + +# Do ping +echo "Pinging" +ping6 $IPADDR -c $COUNT | tee $BASENAME.scriptlog +# Fetch ping6 status code (not $? because this is piped) +STATUS=${PIPESTATUS[0]} +REPLIES=`grep -c 'icmp_seq=' $BASENAME.scriptlog` + +echo "Closing simulation and tunslip6" +sleep 1 +kill -9 $JPID +kill -9 $MPID +sleep 1 +rm COOJA.testlog +rm COOJA.log + +if [ $STATUS -eq 0 ] && [ $REPLIES -eq $COUNT ] ; then + printf "%-32s TEST OK\n" "$BASENAME" | tee $BASENAME.testlog; +else + echo "==== $BASENAME.coojalog ====" ; cat $BASENAME.coojalog; + echo "==== $BASENAME.tunslip.log ====" ; cat $BASENAME.tunslip.log; + echo "==== $BASENAME.scriptlog ====" ; cat $BASENAME.scriptlog; + + printf "%-32s TEST FAIL\n" "$BASENAME" | tee $BASENAME.testlog; +fi + +# We do not want Make to stop -> Return 0 +# The Makefile will check if a log contains FAIL at the end + +exit 0 diff --git a/tests/17-tun-rpl-br/test-native-border-router.sh b/tests/17-tun-rpl-br/test-native-border-router.sh new file mode 100644 index 0000000000000000000000000000000000000000..38dce1bae9ffed3458ebbc34d1018fcd2fab2eb0 --- /dev/null +++ b/tests/17-tun-rpl-br/test-native-border-router.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 + +# Simulation file +BASENAME=$2 + +# Destination IPv6 +IPADDR=$3 + +# Time allocated for convergence +WAIT_TIME=$4 + +# ICMP request-reply count +COUNT=5 + +# Start simulation +echo "Starting Cooja simulation $BASENAME.csc" +java -Xshare:on -jar $CONTIKI/tools/cooja/dist/cooja.jar -nogui=$BASENAME.csc -contiki=$CONTIKI > $BASENAME.coojalog & +JPID=$! +sleep 20 + +# Connect to the simlation +echo "Starting native border-router" +nohup make -C $CONTIKI/examples/rpl-border-router/ connect-router-cooja TARGET=native >> $BASENAME.nbr.log 2>&1 & +MPID=$! +printf "Waiting for network formation (%d seconds)\n" "$WAIT_TIME" +sleep $WAIT_TIME + +# Do ping +echo "Pinging" +ping6 $IPADDR -c $COUNT | tee $BASENAME.scriptlog +# Fetch ping6 status code (not $? because this is piped) +STATUS=${PIPESTATUS[0]} +REPLIES=`grep -c 'icmp_seq=' $BASENAME.scriptlog` + +echo "Closing simulation and nbr" +sleep 1 +kill -9 $JPID +kill -9 $MPID +sleep 1 +rm COOJA.testlog +rm COOJA.log + +if [ $STATUS -eq 0 ] && [ $REPLIES -eq $COUNT ] ; then + printf "%-32s TEST OK\n" "$BASENAME" | tee $BASENAME.testlog; +else + echo "==== $BASENAME.coojalog ====" ; cat $BASENAME.coojalog; + echo "==== $BASENAME.nbr.log ====" ; cat $BASENAME.nbr.log; + echo "==== $BASENAME.scriptlog ====" ; cat $BASENAME.scriptlog; + + printf "%-32s TEST FAIL\n" "$BASENAME" | tee $BASENAME.testlog; +fi + +# We do not want Make to stop -> Return 0 +# The Makefile will check if a log contains FAIL at the end + +exit 0 diff --git a/tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh b/tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh new file mode 100755 index 0000000000000000000000000000000000000000..9aacc2976f63aaf727f47fe528440ca22b240874 --- /dev/null +++ b/tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 +# Test basename +BASENAME=06-lwm2m-ipso-test + +IPADDR=fd00::302:304:506:708 + +# Starting Contiki-NG native node +echo "Starting native node - lwm2m/ipso objects" +make -C $CONTIKI/examples/lwm2m-ipso-objects clean >/dev/null +make -C $CONTIKI/examples/lwm2m-ipso-objects > make.log 2> make.err +sudo $CONTIKI/examples/lwm2m-ipso-objects/example-ipso-objects.native > node.log 2> node.err & +CPID=$! +sleep 10 + +echo "Downloading leshan" +wget -nc https://joakimeriksson.github.io/resources/leshan-server-demo-1.0.0-SNAPSHOT-jar-with-dependencies.jar +echo "Starting leshan server" +java -jar leshan-server-demo-1.0.0-SNAPSHOT-jar-with-dependencies.jar >leshan.log 2>leshan.err & +LESHID=$! + +COUNTER=10 +while [ $COUNTER -gt 0 ]; do + sleep 5 + if grep -q 'OK' leshan.err ; then + break + fi + let COUNTER-=1 +done + +echo "Closing native node" +sleep 1 +pgrep ipso | sudo xargs kill -9 + +echo "Closing leshan" +sleep 1 +pgrep java | sudo xargs kill -9 + + +if grep -q 'OK' leshan.err ; then + cp leshan.err $BASENAME.testlog; + printf "%-32s TEST OK\n" "$BASENAME" | tee $BASENAME.testlog; +else + echo "==== make.log ====" ; cat make.log; + echo "==== make.err ====" ; cat make.err; + echo "==== node.log ====" ; cat node.log; + echo "==== node.err ====" ; cat node.err; + echo "==== leshan.log ====" ; cat leshan.log; + echo "==== leshan.err ====" ; cat leshan.err; + echo "==== $BASENAME.log ====" ; cat $BASENAME.log; + + printf "%-32s TEST FAIL\n" "$BASENAME" | tee $BASENAME.testlog; +fi + +rm make.log +rm make.err +rm node.log +rm node.err +rm leshan.log +rm leshan.err + +# We do not want Make to stop -> Return 0 +# The Makefile will check if a log contains FAIL at the end +exit 0 diff --git a/tests/18-coap-lwm2m/07-lwm2m-standalone-test.sh b/tests/18-coap-lwm2m/07-lwm2m-standalone-test.sh new file mode 100755 index 0000000000000000000000000000000000000000..b13352447eeb81db3ddce79a26a9b3e48a630aff --- /dev/null +++ b/tests/18-coap-lwm2m/07-lwm2m-standalone-test.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 +# Test basename +BASENAME=07-lwm2m-standalone-test + +# Building standalone posix example +echo "Compiling standalone posix example" +make CONTIKI_NG=../../$CONTIKI -C example-lwm2m-standalone/lwm2m clean >/dev/null +make CONTIKI_NG=../../$CONTIKI -C example-lwm2m-standalone/lwm2m >make.log 2>make.err + +echo "Downloading leshan" +wget -nc https://joakimeriksson.github.io/resources/leshan-server-demo-1.0.0-SNAPSHOT-jar-with-dependencies.jar +echo "Starting leshan server" +java -jar leshan-server-demo-1.0.0-SNAPSHOT-jar-with-dependencies.jar -lp 5686 -slp 5687 >leshan.log 2>leshan.err & +LESHID=$! + +echo "Starting lwm2m standalone example" +example-lwm2m-standalone/lwm2m/lwm2m-example coap://127.0.0.1:5686 > node.log 2> node.err & + +CPID=$! + +COUNTER=10 +while [ $COUNTER -gt 0 ]; do + sleep 5 + if grep -q 'OK' leshan.err ; then + echo OK with $COUNTER + break + fi + let COUNTER-=1 +done + +echo "Closing standalone example" +sleep 1 +pgrep lwm2m-example | sudo xargs kill -9 + +echo "Closing leshan" +sleep 1 +pgrep java | sudo xargs kill -9 + + +if grep -q 'OK' leshan.err ; then + cp leshan.err $BASENAME.testlog; + printf "%-32s TEST OK\n" "$BASENAME" | tee $BASENAME.testlog; +else + echo "==== make.log ====" ; cat make.log; + echo "==== make.err ====" ; cat make.err; + echo "==== node.log ====" ; cat node.log; + echo "==== node.err ====" ; cat node.err; + echo "==== leshan.log ====" ; cat leshan.log; + echo "==== leshan.err ====" ; cat leshan.err; + echo "==== $BASENAME.log ====" ; cat $BASENAME.log; + + printf "%-32s TEST FAIL\n" "$BASENAME" | tee $BASENAME.testlog; +fi + +rm make.log +rm make.err +rm node.log +rm node.err +rm leshan.log +rm leshan.err + +# We do not want Make to stop -> Return 0 +# The Makefile will check if a log contains FAIL at the end +exit 0 diff --git a/tests/18-coap-lwm2m/Makefile b/tests/18-coap-lwm2m/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c46e5271d5a3d2374a99b4d70b09ac5e8870495b --- /dev/null +++ b/tests/18-coap-lwm2m/Makefile @@ -0,0 +1 @@ +include ../Makefile.script-test diff --git a/tests/18-coap-lwm2m/example-lwm2m-standalone b/tests/18-coap-lwm2m/example-lwm2m-standalone new file mode 160000 index 0000000000000000000000000000000000000000..67b858437f7cf1e4e027d821c4c2ac15fdf2ab44 --- /dev/null +++ b/tests/18-coap-lwm2m/example-lwm2m-standalone @@ -0,0 +1 @@ +Subproject commit 67b858437f7cf1e4e027d821c4c2ac15fdf2ab44 diff --git a/tests/18-coap-lwm2m/pytests/test-device.py b/tests/18-coap-lwm2m/pytests/test-device.py new file mode 100644 index 0000000000000000000000000000000000000000..9c441e4a055446e425d46bb48ea63e2bca9ed031 --- /dev/null +++ b/tests/18-coap-lwm2m/pytests/test-device.py @@ -0,0 +1,69 @@ +import unittest, array, time + +class TestDevice(unittest.TestCase): + global client + + def test_available_power_sources(self): + r = client.readTLV("3/0/6") + self.assertEqual(r.getCode().getName(), "CONTENT") + + def test_device_read_JSON(self): + r = client.readJSON("3/0/1") + self.assertEqual(r.getCode().getName(), "CONTENT") + + def test_manufacturer_read(self): + r = client.read("3/0/0") + self.assertEqual(r.getCode().getName(), "CONTENT") + + def test_manufacturer_readJSON(self): + r = client.readJSON("3/0/0") + self.assertEqual(r.getCode().getName(), "CONTENT") + + def test_manufacturer_write(self): + r = client.write(3, 0, 0, "abc"); + self.assertEqual(r.getCode().getName(), "METHOD_NOT_ALLOWED") + + def test_manufacturer_execute(self): + r = client.execute("3/0/0") + self.assertEqual(r.getCode().getName(), "METHOD_NOT_ALLOWED") + + def test_reboot_read(self): + r = client.read("3/0/4") + self.assertEqual(r.getCode().getName(), "METHOD_NOT_ALLOWED") + +# def test_opaque_read(self): +# r = client.readTLV("4711/0/11000") +# v = r.getContent().getValue(); + #print "Result:", v + #print "Type: ", type(v) + #print "Type code: ", v.typecode + #print "Data size: ", len(v) +# self.assertEqual(len(v), 900) + +# def test_object_with_opaque_read(self): +# r = client.readTLV("4711/0/") +# self.assertEqual(r.getCode().getName(), "CONTENT") + + def test_device_time_write(self): + r = client.write(3,0,13,1000) + self.assertEqual(r.getCode().getName(), "CHANGED") + time.sleep(4.9) + r = client.read("3/0/13") + v = r.getContent().getValue().getTime() + self.assertTrue(v > 1000) + print "Time: ", v + + + +print "----------------------------------------" +print "LWM2M Tester - name of client: ", client.endpoint +print "----------------------------------------" + +r = client.read("3/0/0"); +print "Code:", r.getCode(), r.getCode().getName() == "CONTENT" +print "Objects: ", client.links +print "Read Manufacturer => ", client.read("3/0/0") +print "Read Device => ", client.readTLV("3/0/") + +suite = unittest.TestLoader().loadTestsFromTestCase(TestDevice) +unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/Makefile b/tests/Makefile index efa9cc54cb62fe6d9f7919ca4755658365f7af2f..a879c805fa0a5b8f3590de1d9bfc984480fb27bb 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -26,26 +26,20 @@ # SUCH DAMAGE. TESTS=$(wildcard ??-*) -SUMMARIES=$(foreach test,$(TESTS),summary-$(test)) +SUMMARIES=$(foreach test,$(TESTS),$(test)/summary) CONTIKI=.. run: clean summary summary: $(SUMMARIES) - grep '' $(SUMMARIES) > summary + @cat $(SUMMARIES) > $@ -summary-%: - @make -C $* RUNALL=true summary || true - @echo -n $* | cat - $*/summary > $@ - @rm $*/summary +%/summary: + @make -C $* summary || true clean: - rm -f $(SUMMARIES) - -cooja: $(CONTIKI)/tools/cooja/dist/cooja.jar -$(CONTIKI)/tools/cooja/dist/cooja.jar: - (cd $(CONTIKI)/tools/cooja; ant jar) + rm -f $(SUMMARIES) summary scan-build: cd scan_build && scan-build $(MAKE) diff --git a/tests/Makefile.compile-test b/tests/Makefile.compile-test index fa0f1cf79d1b33c4f2e65e39130209bd6a142e00..1a59520333c1d4c5802b134083d87f8f0d05a57a 100644 --- a/tests/Makefile.compile-test +++ b/tests/Makefile.compile-test @@ -25,9 +25,7 @@ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. -all: summary - -build: examples tools +all: clean summary # The stuff below is some GNU make magic to automatically make make # give each compile test a number, prefixed with a 0 if the number is @@ -40,13 +38,13 @@ get_target = $(firstword $(subst :, ,$1)) get_target_vars = $(wordlist 2,15,$(subst :, ,$1)) define dooneexample -@echo Building example $(3): $(1) $(4) for target $(2) +@echo -n Building example $(3): $(1) $(4) for target $(2) @((cd $(EXAMPLESDIR)/$(1); \ - make $(4) TARGET=$(2) clean && make $(4) TARGET=$(2) WERROR=1) > \ - $(3)-$(subst /,-,$(1))$(2).report 2>&1 && \ - (echo $(1) $(2): OK | tee $(3)-$(subst /,-,$(1))$(2).summary) || \ - (echo $(1) $(2): FAIL ಠ.ಠ | tee $(3)-$(subst /,-,$(1))$(2).summary ; \ - tail -10 $(3)-$(subst /,-,$(1))$(2).report | tee $(3)-$(subst /,-,$(1))$(2).faillog)) + make $(4) TARGET=$(2) clean && make -j $(4) TARGET=$(2) WERROR=1) > \ + /dev/null 2>make.err && \ + (echo " -> OK" && printf "%-75s %-40s %-20s TEST OK\n" "$(1)" "$(4)" "$(2)" > $(3)-$(subst /,-,$(1))$(2).testlog) || \ + (echo " -> FAIL" && printf "%-75s %-40s %-20s TEST FAIL\n" "$(1)" "$(4)" "$(2)" > $(3)-$(subst /,-,$(1))$(2).testlog ; cat make.err)) +@rm -f make.err endef define doexample @@ -55,40 +53,16 @@ $(call dooneexample,$(dir $(call get_target,${1})),$(notdir $(call get_target,${ endef #end of GNU make magic - examples: $(foreach ex, $(EXAMPLES), $(call doexample, ${ex})) -report: build - @echo Examples | cat - ??-*.report > report - @echo Tools | cat - $(foreach tool, $(TOOLS), $(tool).report) >> report - -examples-summary: build - @echo Example summary | cat - $(foreach example, $(EXAMPLES), \ - $(foreach target, $(EXAMPLESTARGETS), $(example)-$(target).summary)) > \ - $@ - @echo Tools summary | cat - $(foreach tool, $(TOOLS), $(tool).summary) >> $@ - -faillog-summary: build - @rm -f $@; touch $@ - @$(foreach log, $(wildcard *.faillog), grep -H '' $(log) >> $@;) - -summary: examples-summary faillog-summary - @cat *.summary > $@ - @ls -1 ??-*.faillog > /dev/null 2>&1; [ $$? = 0 ] && tail -v ??-*.faillog >> $@ || true - @rm -f $^ - -tools: - @$(foreach tool, $(TOOLS), \ - (((cd $(TOOLSDIR)/$(tool); make) > $(tool).report 2>&1) && \ - (echo $(tool): OK | tee $(tool).summary) || \ - (echo $(tool): FAIL ಠ_ಠ | tee $(tool).summary ; \ - tail -10 $(tool).report > $(tool).faillog)) ; ) +summary: examples + @cat *.testlog > summary + @echo "========== Summary ==========" + @cat summary clean: - @rm -f *.summary *.report *.faillog summary report + @rm -f *.testlog summary @$(foreach example, $(EXAMPLES), \ $(foreach target, $(EXAMPLESTARGETS), \ (cd $(EXAMPLESDIR)/$(example); make TARGET=$(target) clean);)) - @$(foreach tool, $(TOOLS), \ - (cd $(TOOLSDIR)/$(tool); make clean);) diff --git a/tests/Makefile.script-test b/tests/Makefile.script-test new file mode 100644 index 0000000000000000000000000000000000000000..e4dd0da6a6132d14b5481e38619b22e5f83bed87 --- /dev/null +++ b/tests/Makefile.script-test @@ -0,0 +1,22 @@ +TESTS=$(wildcard ??-*.sh) +TESTLOGS=$(sort $(patsubst %.sh,%.testlog,$(TESTS))) + +CONTIKI=../.. + +all: clean summary + +summary: cooja $(TESTLOGS) + @cat *.testlog > summary + @echo "========== Summary ==========" + @cat summary + +%.testlog: %.sh cooja + @echo "========== Running script test $(basename $@).sh ==========" + @bash "$(basename $@).sh" "$(CONTIKI)" + +clean: + @rm -f *.*log report summary + +cooja: $(CONTIKI)/tools/cooja/dist/cooja.jar +$(CONTIKI)/tools/cooja/dist/cooja.jar: + (cd $(CONTIKI)/tools/cooja; ant jar) diff --git a/tests/Makefile.simulation-test b/tests/Makefile.simulation-test index bbd54703ce480719ba934d957d3653a21874b70f..618419dc6a40fe8d3d308dedcc7b3544154724db 100644 --- a/tests/Makefile.simulation-test +++ b/tests/Makefile.simulation-test @@ -25,46 +25,35 @@ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. +all: cooja summary TESTS=$(wildcard ??-*.csc) -TESTLOGS=$(patsubst %.csc,%.testlog,$(TESTS)) -LOGS=$(patsubst %.csc,%.log,$(TESTS)) -FAILLOGS=$(patsubst %.csc,%.*.faillog,$(TESTS)) -#Set random seeds to create reproduceable results. -RANDOMSEED=1 +TESTLOGS=$(sort $(patsubst %.csc,%.testlog,$(TESTS))) + +# The random seed to start from +BASESEED ?= 1 +# The number of runs (with different random seeds) +RUNCOUNT ?= 1 CONTIKI=../.. tests: $(TESTLOGS) -report: clean tests - @echo | grep -s -e '' - $(LOGS) $(TESTLOGS) $(FAILLOGS) > $@ || true - -summary: report +summary: clean tests ifeq ($(TESTS),) - @echo No tests > $@ -else - @egrep -e ' OK| FAIL' $< > $@ - @ls -1 ??-*.faillog > /dev/null 2>&1; [ $$? = 0 ] && tail -v ??-*.log ??-*.faillog >> $@ || true -endif - -all: cooja clean tests - -ifdef RUNALL -RUNALL=true + @echo No tests > summary else -RUNALL=false + @cat $(TESTLOGS) > summary endif + @echo "========== Summary ==========" + @cat summary -%.testlog: %.csc cooja - @$(CONTIKI)/tests/simexec.sh "$(RUNALL)" "$<" "$(CONTIKI)" "$(basename $@)" $(RANDOMSEED) +%.testlog: %.csc cooja + @$(CONTIKI)/tests/simexec.sh "$<" "$(CONTIKI)" "$(basename $@)" $(BASESEED) $(RUNCOUNT) clean: - @rm -f $(TESTLOGS) $(LOGS) $(FAILLOGS) COOJA.log COOJA.testlog \ - report summary - + @rm -f *.*log report summary cooja: $(CONTIKI)/tools/cooja/dist/cooja.jar $(CONTIKI)/tools/cooja/dist/cooja.jar: (cd $(CONTIKI)/tools/cooja; ant jar) - diff --git a/tests/check-test.sh b/tests/check-test.sh new file mode 100755 index 0000000000000000000000000000000000000000..c59ee873b397052542a7723f7ca5799f0d607ed0 --- /dev/null +++ b/tests/check-test.sh @@ -0,0 +1,10 @@ +#!/bin/bash +FAILS=`grep -c 'TEST FAIL' $1/summary` +echo "======== Test outcome =======" +if [ -f "$1/summary" ] && [ $FAILS == 0 ]; then + printf "Test %s OK\n" "$1" + exit 0 +else + printf "Test %s FAIL\n" "$1" + exit 1 +fi diff --git a/tests/compile-all/Makefile b/tests/compile-all/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1bd79315cd02a4cb0211e8f66be31934556bf4bb --- /dev/null +++ b/tests/compile-all/Makefile @@ -0,0 +1,5 @@ +all: + ./build.sh all + +clean: + ./build.sh clean diff --git a/tests/compile-all/build.sh b/tests/compile-all/build.sh new file mode 100755 index 0000000000000000000000000000000000000000..795343eebe7db9f9d31652cb51aac1390990b341 --- /dev/null +++ b/tests/compile-all/build.sh @@ -0,0 +1,157 @@ +#!/bin/bash + +# Copyright (c) 2018, University of Bristol +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# Author: Atis Elsts + +# +# This file builds all examples for all platforms, excluding just those +# example and platform combinations that are marked as impossible in the Makefiles +# by using PLATFORMS_EXCLUDE and PLATFORMS_ONLY variables. +# +# This script can also clean all targets. To do that, run: +# ./build.sh clean +# +# To invoke the building for a specific platform, run: +# $ PLATFORMS=zoul ./build.sh +# + +if [[ "$PLATFORMS" == "" ]] +then + PLATFORMS=`ls ../../arch/platform` +fi + +if [[ "$MAKEFILES" == "" ]] +then + MAKEFILES=`find ../../examples/ -name Makefile` +fi + +# Set the make goal the first argument of the script or to "all" if called w/o arguments +if [[ $# -gt 0 ]] +then + GOAL=$1 +else + GOAL="all" +fi + +# Logging level: +# 0 - quiet +# 1 - normal; prints compilation and link messages only on errors +# 2 - print all compilation and link messages +LOG_LEVEL=1 + +if [[ $LOG_LEVEL -ge 1 ]] +then + LOG_INFO=echo + CAT_INFO=cat +else + LOG_INFO=true + CAT_INFO=true +fi + +if [[ $LOG_LEVEL -ge 2 ]] +then + LOG_DEBUG=echo + CAT_DEBUG=cat +else + LOG_DEBUG=true + CAT_DEBUG=true +fi + +NUM_SUCCESS=0 +NUM_FAILED=0 + +FAILED= + +for platform in $PLATFORMS +do + # Cooja is not very friendly for command line builds at the moment + if [[ "$platform" == "cooja" ]] + then + $LOG_INFO "Skipping the Cooja platform" + continue + fi + + if [[ "$platform" == "srf06-cc26xx" ]] + then + # srf06-cc26xx has multiple boards + BOARDS="srf06/cc26xx srf06/cc13xx launchpad/cc2650 launchpad/cc1350 sensortag/cc2650 sensortag/cc1350" + elif [[ "$platform" == "zoul" ]] + then + # Zoul has multiple boards + BOARDS="remote-reva remote-revb firefly-reva firefly orion" + else + # Other platforms have just a single board + BOARDS="default" + fi + + $LOG_INFO "=====================================================" + $LOG_INFO "Going through all examples for platform \"$platform\"" + $LOG_INFO "=====================================================" + for example in $MAKEFILES + do + + for board in $BOARDS + do + example_dir=`dirname "$example"` + + # Clean it before building + make -C "$example_dir" TARGET=$platform BOARD=$board clean 2>&1 >/dev/null + if [[ "$GOAL" == "clean" ]] + then + # do this just for the first board + break + fi + + # Build the goal + $LOG_INFO "make -C \"$example_dir\" -j TARGET=$platform BOARD=$board $GOAL" + if make -C "$example_dir" -j TARGET=$platform BOARD=$board $GOAL 2>&1 >build.log + then + $LOG_INFO "..done" + $CAT_DEBUG build.log + NUM_SUCCESS=$(($NUM_SUCCESS + 1)) + else + $LOG_INFO "Failed to build $example_dir for $platform ($board)" + $CAT_DEBUG build.log + NUM_FAILED=$(($NUM_FAILED + 1)) + FAILED="$FAILED; $example_dir for $platform ($board)" + fi + + # Clean it after building + make -C "$example_dir" TARGET=$platform BOARD=$board clean 2>&1 >/dev/null + done + done +done + +# If building, not cleaning, print so statistics +if [[ "$GOAL" == "all" ]] +then + $LOG_INFO "Number of examples skipped or built successfully: $NUM_SUCCESS" + $LOG_INFO "Number of examples that failed to build: $NUM_FAILED" + $LOG_INFO "Failed examples: $FAILED" +fi diff --git a/tests/simexec.sh b/tests/simexec.sh index b4bc91e16f5ae1c71226f9b538870b58178dca97..31b8bcdf87581b86c6597020771fb51a5631bbfb 100755 --- a/tests/simexec.sh +++ b/tests/simexec.sh @@ -1,7 +1,4 @@ #!/bin/bash -# Do not return an error -RUNALL=$1 -shift # The simulation to run CSC=$1 shift @@ -11,77 +8,71 @@ shift #The basename of the experiment BASENAME=$1 shift -# The test will end on the first successfull run +#The random seed to start from +BASESEED=$1 +shift +#The number of runs (with different seeds) +RUNCOUNT=$1 +shift + +# Counts all tests run +declare -i TESTCOUNT=0 -#set -x +# Counts successfull tests +declare -i OKCOUNT=0 -while (( "$#" )); do - RANDOMSEED=$1 - echo -n "Running test $BASENAME with random Seed $RANDOMSEED: " +# A list of seeds the resulted in failure +FAILSEEDS= - java -Xshare:on -jar $CONTIKI/tools/cooja/dist/cooja.jar -nogui=$CSC -contiki=$CONTIKI -random-seed=$RANDOMSEED > $BASENAME.log & +for (( SEED=$BASESEED; SEED<$(($BASESEED+$RUNCOUNT)); SEED++ )); do + echo -n "Running test $BASENAME with random Seed $SEED" + + # run simulation + java -Xshare:on -jar $CONTIKI/tools/cooja/dist/cooja.jar -nogui=$CSC -contiki=$CONTIKI -random-seed=$SEED > $BASENAME.$SEED.coojalog & JPID=$! # Copy the log and only print "." if it changed - touch $BASENAME.log.prog + touch progress.log while kill -0 $JPID 2> /dev/null do sleep 1 - diff $BASENAME.log $BASENAME.log.prog > /dev/null - if [ $? -ne 0 ] + diff $BASENAME.$SEED.coojalog progress.log > /dev/null + if [ $? -ne 0 ] then echo -n "." - cp $BASENAME.log $BASENAME.log.prog + cp $BASENAME.$SEED.coojalog progress.log fi done - rm $BASENAME.log.prog - + rm progress.log + # wait for end of simulation wait $JPID JRV=$? + # Save testlog + touch COOJA.testlog; + mv COOJA.testlog $BASENAME.$SEED.scriptlog + rm COOJA.log + + TESTCOUNT+=1 if [ $JRV -eq 0 ] ; then - touch COOJA.testlog; - mv COOJA.testlog $BASENAME.testlog + OKCOUNT+=1 echo " OK" - exit 0 - fi - - - - # In case of failure - - - - #Verbose output when using CI - if [ "$CI" = "true" ]; then - echo "==== $BASENAME.log ====" ; cat $BASENAME.log; - echo "==== COOJA.testlog ====" ; cat COOJA.testlog; - echo "==== Files used for simulation (sha1sum) ====" - grep "Loading firmware from:" COOJA.log | cut -d " " -f 10 | uniq | xargs -r sha1sum - grep "Creating core communicator between Java class" COOJA.log | cut -d " " -f 17 | uniq | xargs -r sha1sum else - tail -50 $BASENAME.log ; - fi; - - mv COOJA.testlog $BASENAME.$RANDOMSEED.faillog - - shift + FAILSEEDS+=" $BASESEED" + echo " FAIL" + echo "==== $BASENAME.$SEED.coojalog ====" ; cat $BASENAME.$SEED.coojalog; + echo "==== $BASENAME.$SEED.scriptlog ====" ; cat $BASENAME.$SEED.scriptlog; + fi done -#All seeds failed - echo " FAIL ಠ_ಠ" | tee -a $BASENAME.$RANDOMSEED.faillog; - -# We do not want Make to stop -> Return 0 -if [ "$RUNALL" = "true" ] ; then - touch COOJA.testlog; - mv COOJA.testlog $BASENAME.testlog; - exit 0 +if [ $TESTCOUNT -ne $OKCOUNT ] ; then + # At least one test failed + printf "%-40s TEST FAIL %3d/%d -- failed seeds:%s\n" "$BASENAME" "$OKCOUNT" "$TESTCOUNT" "$FAILSEEDS" > $BASENAME.testlog; +else + printf "%-40s TEST OK %3d/%d\n" "$BASENAME" "$OKCOUNT" "$TESTCOUNT" > $BASENAME.testlog; fi - -exit 1 - - - - +# We do not want Make to stop -> Return 0 +# The Makefile will check if a log contains FAIL at the end +exit 0 diff --git a/tools/Makefile b/tools/Makefile index 798426cb95cac48baca8b38b612d179256a99942..ef1711d7c48f3e1acee3ee29102205cc8f51d487 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,25 +1,8 @@ -all: tunslip +all: tunslip6 + +CFLAGS += -Wall -Werror tunslip6: tools-utils.c tunslip6.c -gitclean: - @git clean -d -x -n .. - @echo "Enter yes to delete these files"; - @read response;if [[ "$$response" = "yes" ]]; then git clean -d -f -x ..;fi; - -distclean: cleanobj cleanfiles cleantargets cleandone -cleanobj: - ${info Removing obj_* directories...} - @find ../examples/ -name "obj_*" -print -exec rm -R '{}' + -cleanfiles: - ${info Removing .map, .co, .ce, contiki*.a files...} - @find ../examples -name "*.map" -print -delete - @find ../examples -name "*.co" -print -delete - @find ../examples -name "*.ce" -print -delete - @find ../examples -name "contiki-*.a" -delete -cleantargets: - ${info Removing .TARGET builds...} - @rm -f -v ${addprefix ../examples/*/*., ${shell ls ../arch/platform/}} - @rm -f -v ${addprefix ../examples/*/*/*., ${shell ls ../arch/platform/}} -cleandone: - @echo ${info All done!} +clean: + rm -f *.o tunslip6 diff --git a/tools/collect-view/build.xml b/tools/collect-view/build.xml deleted file mode 100644 index 5e7458eb7b2477c4b457699a9bf50084d6c89544..0000000000000000000000000000000000000000 --- a/tools/collect-view/build.xml +++ /dev/null @@ -1,78 +0,0 @@ -<?xml version="1.0"?> - -<project name="Sensor Data Collect with Contiki" default="dist" basedir="."> - <property name="java" location="src"/> - <property name="build" location="build"/> - <property name="lib" location="lib"/> - <property name="dist" location="dist"/> - <property name="contiki" location="../.."/> - <property name="archive" value="collect-view.jar"/> - <property name="main" value="org.contikios.contiki.collect.CollectServer"/> - <property name="args" value="" /> - - <path id="classpath"> - <fileset dir="${lib}" includes="**/*.jar"/> - </path> - - <manifestclasspath property="jar.classpath" jarfile="${archive}"> - <classpath refid="classpath" /> - </manifestclasspath> - - <target name="init"> - <tstamp/> - <mkdir dir="${build}"/> - <mkdir dir="${dist}"/> - </target> - - <target name="compile" depends="init"> - <javac srcdir="${java}" destdir="${build}" classpathref="classpath" - debug="true" includeantruntime="false" /> - </target> - - <target name="jar" depends="compile"> - <jar destfile="${dist}/${archive}" basedir="${build}"> - <manifest> - <attribute name="Main-Class" value="${main}"/> - <attribute name="Class-Path" value="${jar.classpath}" /> - </manifest> - </jar> - <mkdir dir="${dist}/lib"/> - <copy todir="${dist}/lib"> - <fileset dir="${lib}"/> - </copy> - </target> - - <condition property="collect-view-shell.exists"> - <available file="${dist}/collect-view-shell.ihex"/> - </condition> - - <target name="collect-view-shell.ihex" unless="collect-view-shell.exists" depends="init"> - <exec dir="${contiki}/examples/collect" executable="make"> - <arg value="TARGET=sky"/> - <arg value="collect-view-shell.ihex"/> - </exec> - <copy todir="${dist}" file="${contiki}/examples/collect/collect-view-shell.ihex"/> - </target> - - <target name="dist" depends="jar,collect-view-shell.ihex"> - <copy todir="${dist}" file="collect-init.script"/> - <mkdir dir="${dist}/tools"/> - <copy todir="${dist}/tools"> - <fileset dir="${contiki}/tools/sky"/> - </copy> - <copy file="${contiki}/tools/cygwin/cygwin1.dll" todir="${dist}/tools"/> - <chmod dir="${dist}/tools" perm="a+x" includes="**/*"/> - </target> - - <target name="run" depends="dist"> - <java fork="yes" dir="${dist}" jar="${dist}/${archive}"> - <arg line="${args}"/> - </java> - </target> - - <target name="clean"> - <delete dir="${build}"/> - <delete dir="${dist}"/> - </target> - -</project> diff --git a/tools/collect-view/collect-init.script b/tools/collect-view/collect-init.script deleted file mode 100644 index 493cd46c564543203c4787fe12d89af311a4cbcd..0000000000000000000000000000000000000000 --- a/tools/collect-view/collect-init.script +++ /dev/null @@ -1,6 +0,0 @@ -echo ~K -echo killall -sleep 2 -echo mac 0 -sleep 2 -echo time %TIME% | null diff --git a/tools/collect-view/lib/jcommon-1.0.13.jar b/tools/collect-view/lib/jcommon-1.0.13.jar deleted file mode 100644 index 634447d2f275b2bd8112db801fce42d143979654..0000000000000000000000000000000000000000 Binary files a/tools/collect-view/lib/jcommon-1.0.13.jar and /dev/null differ diff --git a/tools/collect-view/lib/jfreechart-1.0.10.jar b/tools/collect-view/lib/jfreechart-1.0.10.jar deleted file mode 100644 index f6f7bbf2d45717843d6404c85e994b66a90806ef..0000000000000000000000000000000000000000 Binary files a/tools/collect-view/lib/jfreechart-1.0.10.jar and /dev/null differ diff --git a/tools/collect-view/src/org/contikios/contiki/collect/CollectServer.java b/tools/collect-view/src/org/contikios/contiki/collect/CollectServer.java deleted file mode 100644 index 582a4dacdba53a85e3414d60cc80dbfbd74353c5..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/CollectServer.java +++ /dev/null @@ -1,1592 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * ----------------------------------------------------------------- - * - * CollectServer - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - */ - -package org.contikios.contiki.collect; -import java.awt.BorderLayout; -import java.awt.GraphicsEnvironment; -import java.awt.Rectangle; -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Map; -import java.util.Properties; -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.DefaultListModel; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JScrollPane; -import javax.swing.JTabbedPane; -import javax.swing.ListCellRenderer; -import javax.swing.SwingUtilities; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.axis.ValueAxis; -import org.contikios.contiki.collect.gui.AggregatedTimeChartPanel; -import org.contikios.contiki.collect.gui.BarChartPanel; -import org.contikios.contiki.collect.gui.MapPanel; -import org.contikios.contiki.collect.gui.NodeControl; -import org.contikios.contiki.collect.gui.NodeInfoPanel; -import org.contikios.contiki.collect.gui.SerialConsole; -import org.contikios.contiki.collect.gui.TimeChartPanel; - -/** - * - */ -public class CollectServer implements SerialConnectionListener { - - public static final String WINDOW_TITLE = "Sensor Data Collect with Contiki"; - public static final String STDIN_COMMAND = "<STDIN>"; - - public static final String CONFIG_FILE = "collect.conf"; - public static final String SENSORDATA_FILE = "sensordata.log"; - public static final String CONFIG_DATA_FILE = "collect-data.conf"; - public static final String INIT_SCRIPT = "collect-init.script"; - public static final String FIRMWARE_FILE = "collect-view-shell.ihex"; - - /* Categories for the tab pane */ - private static final String MAIN = "main"; - private static final String NETWORK = "Network"; - private static final String SENSORS = "Sensors"; - private static final String POWER = "Power"; - - private Properties config = new Properties(); - - private String configFile; - private Properties configTable = new Properties(); - - private ArrayList<SensorData> sensorDataList = new ArrayList<SensorData>(); - private PrintWriter sensorDataOutput; - private boolean isSensorLogUsed; - - private Hashtable<String,Node> nodeTable = new Hashtable<String,Node>(); - private Node[] nodeCache; - - private JFrame window; - private JTabbedPane mainPanel; - private HashMap<String,JTabbedPane> categoryTable = new HashMap<String,JTabbedPane>(); - private JMenuItem runInitScriptItem; - - private final Visualizer[] visualizers; - private final MapPanel mapPanel; - private final SerialConsole serialConsole; - private final ConnectSerialAction connectSerialAction; - private final MoteProgramAction moteProgramAction; - private JFileChooser fileChooser; - - private JList nodeList; - private DefaultListModel nodeModel; - private Node[] selectedNodes; - - private SerialConnection serialConnection; - private boolean hasSerialOpened; - /* Do not auto send init script at startup */ - private boolean doSendInitAtStartup = false; - private String initScript; - - private boolean hasStarted = false; - private boolean doExitOnRequest = true; - private JMenuItem exitItem; - - private int defaultMaxItemCount = 250; - private long nodeTimeDelta; - - @SuppressWarnings("serial") - public CollectServer() { - loadConfig(config, CONFIG_FILE); - - this.configFile = config.getProperty("config.datafile", CONFIG_DATA_FILE); - if (this.configFile != null) { - loadConfig(configTable, this.configFile); - } - this.initScript = config.getProperty("init.script", INIT_SCRIPT); - - /* Make sure we have nice window decorations */ -// JFrame.setDefaultLookAndFeelDecorated(true); -// JDialog.setDefaultLookAndFeelDecorated(true); - Rectangle maxSize = GraphicsEnvironment.getLocalGraphicsEnvironment() - .getMaximumWindowBounds(); - - /* Create and set up the window */ - window = new JFrame(WINDOW_TITLE + " (not connected)"); - window.setLocationByPlatform(true); - if (maxSize != null) { - window.setMaximizedBounds(maxSize); - } - window.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - - window.addWindowListener(new WindowAdapter() { - - public void windowClosing(WindowEvent e) { - exit(); - } - }); - - moteProgramAction = new MoteProgramAction("Program Nodes..."); - connectSerialAction = new ConnectSerialAction("Connect to serial"); - - nodeModel = new DefaultListModel(); - nodeModel.addElement("<All>"); - nodeList = new JList(nodeModel); - nodeList.setPrototypeCellValue("888.888"); - nodeList.addListSelectionListener(new ListSelectionListener() { - - @Override - public void valueChanged(ListSelectionEvent e) { - if (!e.getValueIsAdjusting() && e.getSource() == nodeList) { - Node[] selected; - int iMin = nodeList.getMinSelectionIndex(); - int iMax = nodeList.getMaxSelectionIndex(); - if ((iMin < 0) || (iMax < 0)) { - selected = null; - } else if (nodeList.getSelectedIndex() == 0) { - selected = getNodes(); - if (nodeModel.size() > 1) { - nodeList.setSelectionInterval(1, nodeModel.size() - 1); - } - } else { - Node[] tmp = new Node[1 + (iMax - iMin)]; - int n = 0; - if (iMin < 1) { - iMin = 1; - } - for(int i = iMin; i <= iMax; i++) { - if (nodeList.isSelectedIndex(i)) { - tmp[n++] = (Node) nodeModel.getElementAt(i); - } - } - if (n != tmp.length) { - Node[] t = new Node[n]; - System.arraycopy(tmp, 0, t, 0, n); - tmp = t; - } - selected = tmp; - } - selectNodes(selected, false); - } - - }}); - nodeList.setBorder(BorderFactory.createTitledBorder("Nodes")); - ListCellRenderer renderer = nodeList.getCellRenderer(); - if (renderer instanceof JLabel) { - ((JLabel)renderer).setHorizontalAlignment(JLabel.CENTER); - } - window.getContentPane().add(new JScrollPane(nodeList), BorderLayout.WEST); - - mainPanel = new JTabbedPane(); - mainPanel.setBackground(nodeList.getBackground()); - mainPanel.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT); - categoryTable.put(MAIN, mainPanel); - - serialConsole = new SerialConsole(this, MAIN); - mapPanel = new MapPanel(this, "Sensor Map", MAIN, true); - String image = getConfig("collect.mapimage"); - if (image != null) { - mapPanel.setMapBackground(image); - } - NodeControl nodeControl = new NodeControl(this, MAIN); - - visualizers = new Visualizer[] { - nodeControl, - mapPanel, - new MapPanel(this, "Network Graph", MAIN, false), - new BarChartPanel(this, SENSORS, "Average Temperature", "Temperature", "Nodes", "Celsius", - new String[] { "Celsius" }) { - { - chart.getCategoryPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - String nodeName = node.getName(); - SensorDataAggregator aggregator = node.getSensorDataAggregator(); - dataset.addValue(aggregator.getAverageTemperature(), categories[0], nodeName); - } - }, - new TimeChartPanel(this, SENSORS, "Temperature", "Temperature", "Time", "Celsius") { - { - chart.getXYPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - setRangeTick(5); - setRangeMinimumSize(10.0); - setGlobalRange(true); - } - protected double getSensorDataValue(SensorData data) { - return data.getTemperature(); - } - }, - new TimeChartPanel(this, SENSORS, "Battery Voltage", "Battery Voltage", - "Time", "Volt") { - { - setRangeTick(1); - setRangeMinimumSize(4.0); - setGlobalRange(true); - } - protected double getSensorDataValue(SensorData data) { - return data.getBatteryVoltage(); - } - }, - new TimeChartPanel(this, SENSORS, "Battery Indicator", "Battery Indicator", - "Time", "Indicator") { - { - chart.getXYPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - setRangeTick(5); - setRangeMinimumSize(10.0); - setGlobalRange(true); - } - protected double getSensorDataValue(SensorData data) { - return data.getBatteryIndicator(); - } - }, - new TimeChartPanel(this, SENSORS, "Relative Humidity", "Humidity", "Time", "%") { - { - chart.getXYPlot().getRangeAxis().setRange(0.0, 100.0); - } - protected double getSensorDataValue(SensorData data) { - return data.getHumidity(); - } - }, - new TimeChartPanel(this, SENSORS, "Light 1", "Light 1", "Time", "-") { - protected double getSensorDataValue(SensorData data) { - return data.getLight1(); - } - }, - new TimeChartPanel(this, SENSORS, "Light 2", "Light 2", "Time", "-") { - protected double getSensorDataValue(SensorData data) { - return data.getLight2(); - } - }, - new TimeChartPanel(this, NETWORK, "Neighbors", "Neighbor Count", "Time", "Neighbors") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected double getSensorDataValue(SensorData data) { - return data.getValue(SensorData.NUM_NEIGHBORS); - } - }, - new TimeChartPanel(this, NETWORK, "Beacon Interval", "Beacon interval", "Time", "Interval (s)") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected double getSensorDataValue(SensorData data) { - return data.getValue(SensorData.BEACON_INTERVAL); - } - }, - new TimeChartPanel(this, NETWORK, "Network Hops (Over Time)", "Network Hops", "Time", "Hops") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected double getSensorDataValue(SensorData data) { - return data.getValue(SensorData.HOPS); - } - }, - new BarChartPanel(this, NETWORK, "Network Hops (Per Node)", "Network Hops", "Nodes", "Hops", - new String[] { "Last Hop", "Average Hops" }, false) { - { - chart.getCategoryPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected void addSensorData(SensorData data) { - dataset.addValue(data.getValue(SensorData.HOPS), categories[0], data.getNode().getName()); - dataset.addValue(data.getNode().getSensorDataAggregator().getAverageValue(SensorData.HOPS), categories[1], data.getNode().getName()); - } - }, - new TimeChartPanel(this, NETWORK, "Routing Metric (Over Time)", "Routing Metric", "Time", "Routing Metric") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected double getSensorDataValue(SensorData data) { - return data.getValue(SensorData.RTMETRIC); - } - }, - new AggregatedTimeChartPanel<boolean[]>(this, NETWORK, "Avg Routing Metric (Over Time)", "Time", - "Average Routing Metric") { - private int nodeCount; - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - @Override - protected boolean[] createState(Node node) { - return new boolean[1]; - } - @Override - protected void clearState(Map<Node,boolean[]> map) { - nodeCount = 0; - for(boolean[] value : map.values()) { - value[0] = false; - } - } - @Override - protected String getTitle(int selectedCount, int dataCount, int duplicateCount) { - return "Average Routing Metric (" + dataCount + " packets from " + nodeCount + " node" - + (nodeCount > 1 ? "s" : "") + ')'; - } - @Override - protected int getTotalDataValue(int value) { - // Return average value - return nodeCount > 0 ? (value / nodeCount) : value; - } - @Override - protected int getSensorDataValue(SensorData data, boolean[] nodeState) { - if (!nodeState[0]) { - nodeCount++; - nodeState[0] = true; - } - return data.getValue(SensorData.RTMETRIC); - } - }, - new TimeChartPanel(this, NETWORK, "ETX (Over Time)", "ETX to Next Hop", "Time", "ETX") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected double getSensorDataValue(SensorData data) { - return data.getBestNeighborETX(); - } - }, - new AggregatedTimeChartPanel<int[]>(this, NETWORK, - "Next Hop (Over Time)", "Time", "Next Hop Changes") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - @Override - protected int[] createState(Node node) { - return new int[1]; - } - @Override - protected void clearState(Map<Node,int[]> map) { - for(int[] value : map.values()) { - value[0] = 0; - } - } - @Override - protected int getSensorDataValue(SensorData sd, int[] nodeState) { - boolean hasBest = nodeState[0] != 0; - int bestNeighbor = sd.getValue(SensorData.BEST_NEIGHBOR); - if (bestNeighbor != 0 && bestNeighbor != nodeState[0]) { - nodeState[0] = bestNeighbor; - return hasBest ? 1 : 0; - } - return 0; - } - }, - new TimeChartPanel(this, NETWORK, "Latency", "Latency", "Time", "Seconds") { - protected double getSensorDataValue(SensorData data) { - return data.getLatency(); - } - }, - new AggregatedTimeChartPanel<Node>(this, NETWORK, - "Received (Over Time)", "Time", "Received Packets") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - @Override - protected String getTitle(int nodeCount, int dataCount, int duplicateCount) { - return "Received " + dataCount + " packets from " + nodeCount + " node" - + (nodeCount > 1 ? "s" : "") - + (duplicateCount > 0 ? (" (" + duplicateCount + " duplicates)") : ""); - } - @Override - protected Node createState(Node node) { - return node; - } - @Override - protected int getSensorDataValue(SensorData sd, Node node) { - return 1; - } - }, - new AggregatedTimeChartPanel<int[]>(this, NETWORK, - "Lost (Over Time)", "Time", "Estimated Lost Packets") { - private int totalLost; - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - @Override - protected String getTitle(int nodeCount, int dataCount, int duplicateCount) { - return "Received " + dataCount + " packets from " + nodeCount - + " node" + (nodeCount > 1 ? "s" : "") + ". Estimated " - + totalLost + " lost packet" + (totalLost == 1 ? "" : "s") - + '.'; - } - @Override - protected int[] createState(Node node) { - return new int[1]; - } - @Override - protected void clearState(Map<Node,int[]> map) { - totalLost = 0; - for(int[] v : map.values()) { - v[0] = 0; - } - } - @Override - protected int getSensorDataValue(SensorData sd, int[] nodeState) { - int lastSeqno = nodeState[0]; - int seqno = sd.getSeqno(); - nodeState[0] = seqno; - if (seqno > lastSeqno + 1 && lastSeqno != 0) { - int estimatedLost = seqno - lastSeqno - 1; - totalLost += estimatedLost; - return estimatedLost; - } - return 0; - } - }, - new BarChartPanel(this, NETWORK, "Received (Per Node)", "Received Packets Per Node", "Nodes", "Packets", - new String[] { "Packets", "Duplicates" }) { - { - chart.getCategoryPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - SensorDataAggregator sda = node.getSensorDataAggregator(); - dataset.addValue(sda.getDataCount(), categories[0], node.getName()); - dataset.addValue(sda.getDuplicateCount(), categories[1], node.getName()); - } - }, - new BarChartPanel(this, NETWORK, "Received (5 min)", "Received Packets (last 5 min)", "Nodes", "Packets", - new String[] { "Packets", "Duplicates" }) { - { - chart.getCategoryPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - int packetCount = 0; - int duplicateCount = 0; - long earliestData = System.currentTimeMillis() - (5 * 60 * 1000); - for(int index = node.getSensorDataCount() - 1; index >= 0; index--) { - SensorData sd = node.getSensorData(index); - if (sd.getNodeTime() < earliestData) { - break; - } - if (sd.isDuplicate()) { - duplicateCount++; - } else { - packetCount++; - } - } - dataset.addValue(packetCount, categories[0], node.getName()); - dataset.addValue(duplicateCount, categories[1], node.getName()); - } - }, - new BarChartPanel(this, POWER, "Average Power", "Average Power Consumption", - "Nodes", "Power (mW)", - new String[] { "LPM", "CPU", "Radio listen", "Radio transmit" }) { - { - ValueAxis axis = chart.getCategoryPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - String nodeName = node.getName(); - SensorDataAggregator aggregator = node.getSensorDataAggregator(); - dataset.addValue(aggregator.getLPMPower(), categories[0], nodeName); - dataset.addValue(aggregator.getCPUPower(), categories[1], nodeName); - dataset.addValue(aggregator.getListenPower(), categories[2], nodeName); - dataset.addValue(aggregator.getTransmitPower(), categories[3], nodeName); - } - }, - new BarChartPanel(this, POWER, "Radio Duty Cycle", "Average Radio Duty Cycle", - "Nodes", "Duty Cycle (%)", - new String[] { "Radio listen", "Radio transmit" }) { - { - ValueAxis axis = chart.getCategoryPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - String nodeName = node.getName(); - SensorDataAggregator aggregator = node.getSensorDataAggregator(); - dataset.addValue(100 * aggregator.getAverageDutyCycle(SensorInfo.TIME_LISTEN), - categories[0], nodeName); - dataset.addValue(100 * aggregator.getAverageDutyCycle(SensorInfo.TIME_TRANSMIT), - categories[1], nodeName); - } - }, - new BarChartPanel(this, POWER, "Instantaneous Power", - "Instantaneous Power Consumption", "Nodes", "Power (mW)", - new String[] { "LPM", "CPU", "Radio listen", "Radio transmit" }) { - { - ValueAxis axis = chart.getCategoryPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - String nodeName = node.getName(); - dataset.addValue(data.getLPMPower(), categories[0], nodeName); - dataset.addValue(data.getCPUPower(), categories[1], nodeName); - dataset.addValue(data.getListenPower(), categories[2], nodeName); - dataset.addValue(data.getTransmitPower(), categories[3], nodeName); - } - }, - new TimeChartPanel(this, POWER, "Power History", "Historical Power Consumption", "Time", "mW") { - protected double getSensorDataValue(SensorData data) { - return data.getAveragePower(); - } - }, - new NodeInfoPanel(this, MAIN), - serialConsole - }; - for (int i = 0, n = visualizers.length; i < n; i++) { - String category = visualizers[i].getCategory(); - JTabbedPane pane = categoryTable.get(category); - if (pane == null) { - pane = new JTabbedPane(); - pane.setBackground(nodeList.getBackground()); - pane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT); - categoryTable.put(category, pane); - mainPanel.add(category, pane); - } - pane.add(visualizers[i].getTitle(), visualizers[i].getPanel()); - } - JTabbedPane pane = categoryTable.get(nodeControl.getCategory()); - if (pane != null) { - pane.setSelectedComponent(nodeControl.getPanel()); - } - window.getContentPane().add(mainPanel, BorderLayout.CENTER); - - // Setup menu - JMenuBar menuBar = new JMenuBar(); - - JMenu fileMenu = new JMenu("File"); - fileMenu.setMnemonic(KeyEvent.VK_F); - menuBar.add(fileMenu); - fileMenu.add(new JMenuItem(connectSerialAction)); - fileMenu.add(new JMenuItem(moteProgramAction)); - - fileMenu.addSeparator(); - final JMenuItem clearMapItem = new JMenuItem("Remove Map Background"); - clearMapItem.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - mapPanel.setMapBackground(null); - clearMapItem.setEnabled(false); - configTable.remove("collect.mapimage"); - } - - }); - clearMapItem.setEnabled(mapPanel.getMapBackground() != null); - - JMenuItem item = new JMenuItem("Select Map Background..."); - item.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - if (fileChooser == null) { - fileChooser = new JFileChooser(); - } - int reply = fileChooser.showOpenDialog(window); - if (reply == JFileChooser.APPROVE_OPTION) { - File file = fileChooser.getSelectedFile(); - String name = file.getAbsolutePath(); - if (!mapPanel.setMapBackground(file.getAbsolutePath())) { - JOptionPane.showMessageDialog(window, "Failed to set background image", "Error", JOptionPane.ERROR_MESSAGE); - } else { - configTable.put("collect.mapimage", name); - save(); - } - clearMapItem.setEnabled(mapPanel.getMapBackground() != null); - } - } - - }); - fileMenu.add(item); - fileMenu.add(clearMapItem); - - item = new JMenuItem("Save Settings"); - item.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - save(); - JOptionPane.showMessageDialog(window, "Settings have been saved."); - } - - }); - fileMenu.add(item); - - fileMenu.addSeparator(); - item = new JMenuItem("Clear Sensor Data..."); - item.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - int reply = isSensorLogUsed - ? JOptionPane.showConfirmDialog(window, "Also clear the sensor data log file?") - : JOptionPane.NO_OPTION; - if (reply == JOptionPane.YES_OPTION) { - // Clear data from both memory and sensor log file - clearSensorDataLog(); - clearSensorData(); - } else if (reply == JOptionPane.NO_OPTION) { - // Only clear data from memory - clearSensorData(); - } - } - - }); - fileMenu.add(item); - - fileMenu.addSeparator(); - exitItem = new JMenuItem("Exit", KeyEvent.VK_X); - exitItem.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - exit(); - } - - }); - fileMenu.add(exitItem); - - JMenu toolsMenu = new JMenu("Tools"); - toolsMenu.setMnemonic(KeyEvent.VK_T); - menuBar.add(toolsMenu); - - runInitScriptItem = new JMenuItem("Run Init Script"); - runInitScriptItem.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - mainPanel.setSelectedComponent(serialConsole.getPanel()); - if (serialConnection != null && serialConnection.isOpen()) { - runInitScript(); - } else { - JOptionPane.showMessageDialog(mainPanel, "No serial port connection", "No connected node", JOptionPane.ERROR_MESSAGE); - } - } - - }); - runInitScriptItem.setEnabled(false); - toolsMenu.add(runInitScriptItem); - toolsMenu.addSeparator(); - - item = new JMenuItem("Set Max Item Count..."); - item.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - int value = getUserInputAsInteger("Specify Max Item Count", - "Please specify max item count for the time charts.\n" + - "Charts with more values will aggregate the values into fewer items.", - defaultMaxItemCount); - if (value > 0) { - defaultMaxItemCount = value; - if (visualizers != null) { - for(Visualizer v : visualizers) { - if (v instanceof TimeChartPanel) { - ((TimeChartPanel)v).setMaxItemCount(defaultMaxItemCount); - } - } - } - } - } - - }); - toolsMenu.add(item); - - final JCheckBoxMenuItem baseShapeItem = new JCheckBoxMenuItem("Base Shape Visible"); - baseShapeItem.setSelected(true); - baseShapeItem.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - boolean visible = baseShapeItem.getState(); - if (visualizers != null) { - for(Visualizer v : visualizers) { - if (v instanceof TimeChartPanel) { - ((TimeChartPanel)v).setBaseShapeVisible(visible); - } - } - } - } - - }); - toolsMenu.add(baseShapeItem); - - window.setJMenuBar(menuBar); - window.pack(); - - String bounds = configTable.getProperty("collect.bounds"); - if (bounds != null) { - String[] b = bounds.split(","); - if (b.length == 4) { - window.setBounds(Integer.parseInt(b[0]), Integer.parseInt(b[1]), - Integer.parseInt(b[2]), Integer.parseInt(b[3])); - } - } - - for(Object key: configTable.keySet()) { - String property = key.toString(); - if (!property.startsWith("collect")) { - getNode(property, true); - } - } - } - - private int getUserInputAsInteger(String title, String message, int defaultValue) { - String s = (String)JOptionPane.showInputDialog( - window, message, title, JOptionPane.PLAIN_MESSAGE, null, null, Integer.toString(defaultValue)); - if (s != null) { - try { - return Integer.parseInt(s); - } catch (Exception e) { - JOptionPane.showMessageDialog(window, "Illegal value", "Error", JOptionPane.ERROR_MESSAGE); - } - } - return -1; - } - - public void start(SerialConnection connection) { - if (hasStarted) { - throw new IllegalStateException("already started"); - } - hasStarted = true; - this.serialConnection = connection; - if (isSensorLogUsed) { - initSensorData(); - } - SwingUtilities.invokeLater(new Runnable() { - public void run() { - window.setVisible(true); - } - }); - connectToSerial(); - } - - protected void connectToSerial() { - if (serialConnection != null && !serialConnection.isOpen()) { - String comPort = serialConnection.getComPort(); - if (comPort == null && serialConnection.isMultiplePortsSupported()) { - comPort = MoteFinder.selectComPort(window); - } - if (comPort != null || !serialConnection.isMultiplePortsSupported()) { - serialConnection.open(comPort); - } - } - } - - public void stop() { - save(); - if (serialConnection != null) { - serialConnection.close(); - } - PrintWriter output = this.sensorDataOutput; - if (output != null) { - output.close(); - } - window.setVisible(false); - } - - public void setUseSensorDataLog(boolean useSensorLog) { - this.isSensorLogUsed = useSensorLog; - } - - public void setExitOnRequest(boolean doExit) { - this.doExitOnRequest = doExit; - if (exitItem != null) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - exitItem.setEnabled(doExitOnRequest); - } - }); - } - } - - private void exit() { - if (doExitOnRequest) { - stop(); - System.exit(0); - } else { - Toolkit.getDefaultToolkit().beep(); - } - } - - private void sleep(long delay) { - try { - Thread.sleep(delay); - } catch (InterruptedException e1) { - // Ignore - } - } - - protected boolean hasInitScript() { - return initScript != null && new File(initScript).canRead(); - } - - protected void runInitScript() { - if (initScript != null) { - runScript(initScript); - } - } - - protected void runScript(final String scriptFileName) { - new Thread("scripter") { - public void run() { - try { - BufferedReader in = new BufferedReader(new FileReader(scriptFileName)); - String line; - while ((line = in.readLine()) != null) { - if (line.length() == 0 || line.charAt(0) == '#') { - // Ignore empty lines and comments - } else if (line.startsWith("echo ")) { - line = line.substring(5).trim(); - if (line.indexOf('%') >= 0) { - line = line.replace("%TIME%", "" + (System.currentTimeMillis() / 1000)); - } - sendToNode(line); - } else if (line.startsWith("sleep ")) { - long delay = Integer.parseInt(line.substring(6).trim()); - Thread.sleep(delay * 1000); - } else { - System.err.println("Unknown script command: " + line); - break; - } - } - in.close(); - } catch (Exception e) { - System.err.println("Failed to run script: " + scriptFileName); - e.printStackTrace(); - } - } - }.start(); - } - - public String getConfig(String property) { - return getConfig(property, null); - } - - public String getConfig(String property, String defaultValue) { - return configTable.getProperty(property, config.getProperty(property, defaultValue)); - } - - public void setConfig(String property, String value) { - configTable.setProperty(property, value); - } - - public void removeConfig(String property) { - configTable.remove(property); - } - - public int getDefaultMaxItemCount() { - return defaultMaxItemCount; - } - - public Action getMoteProgramAction() { - return moteProgramAction; - } - - public Action getConnectSerialAction() { - return connectSerialAction; - } - - protected void setSystemMessage(final String message) { - SwingUtilities.invokeLater(new Runnable() { - - public void run() { - boolean isOpen = serialConnection != null && serialConnection.isOpen(); - if (message == null) { - window.setTitle(WINDOW_TITLE); - } else { - window.setTitle(WINDOW_TITLE + " (" + message + ')'); - } - connectSerialAction.putValue(ConnectSerialAction.NAME, - isOpen ? "Disconnect from serial" : "Connect to serial"); - runInitScriptItem.setEnabled(isOpen - && serialConnection.isSerialOutputSupported() && hasInitScript()); - } - - }); - } - - // ------------------------------------------------------------------- - // Node Handling - // ------------------------------------------------------------------- - - public synchronized Node[] getNodes() { - if (nodeCache == null) { - Node[] tmp = nodeTable.values().toArray(new Node[nodeTable.size()]); - Arrays.sort(tmp); - nodeCache = tmp; - } - return nodeCache; - } - - public Node addNode(String nodeID) { - return getNode(nodeID, true); - } - - private Node getNode(final String nodeID, boolean notify) { - Node node = nodeTable.get(nodeID); - if (node == null) { - node = new Node(nodeID); - nodeTable.put(nodeID, node); - - synchronized (this) { - nodeCache = null; - } - - if (notify) { - final Node newNode = node; - SwingUtilities.invokeLater(new Runnable() { - public void run() { - boolean added = false; - for (int i = 1, n = nodeModel.size(); i < n; i++) { - int cmp = newNode.compareTo((Node) nodeModel.get(i)); - if (cmp < 0) { - nodeModel.insertElementAt(newNode, i); - added = true; - break; - } else if (cmp == 0) { - // node already added - added = true; - break; - } - } - if (!added) { - nodeModel.addElement(newNode); - } - if (visualizers != null) { - for (int i = 0, n = visualizers.length; i < n; i++) { - visualizers[i].nodeAdded(newNode); - } - } - } - }); - } - } - return node; - } - - public void selectNodes(Node[] nodes) { - selectNodes(nodes, true); - } - - private void selectNodes(Node[] nodes, boolean updateList) { - if (nodes != selectedNodes) { - selectedNodes = nodes; - if (updateList) { - nodeList.clearSelection(); - if (selectedNodes != null) { - for (int i = 0, n = selectedNodes.length; i < n; i++) { - int index = nodeModel.indexOf(selectedNodes[i]); - if (index >= 0) { - nodeList.addSelectionInterval(index, index); - } - } - } - } - if (visualizers != null) { - for (int i = 0, n = visualizers.length; i < n; i++) { - visualizers[i].nodesSelected(nodes); - } - } - } - } - - public Node[] getSelectedNodes() { - return selectedNodes; - } - - - // ------------------------------------------------------------------- - // Node location handling - // ------------------------------------------------------------------- - - private boolean loadConfig(Properties properties, String configFile) { - try { - BufferedInputStream input = - new BufferedInputStream(new FileInputStream(configFile)); - try { - properties.load(input); - } finally { - input.close(); - } - return true; - } catch (FileNotFoundException e) { - // No configuration file exists. - } catch (IOException e) { - System.err.println("Failed to read configuration file: " + configFile); - e.printStackTrace(); - } - return false; - } - - private void save() { - if (configFile != null) { - configTable.setProperty("collect.bounds", "" + window.getX() + ',' + window.getY() + ',' + window.getWidth() + ',' + window.getHeight()); - if (visualizers != null) { - for(Visualizer v : visualizers) { - if (v instanceof Configurable) { - ((Configurable)v).updateConfig(configTable); - } - } - } - saveConfig(configTable, configFile); - } - } - - private void saveConfig(Properties properties, String configFile) { - try { - File fp = new File(configFile); - if (fp.exists()) { - File targetFp = new File(configFile + ".bak"); - if (targetFp.exists()) { - targetFp.delete(); - } - fp.renameTo(targetFp); - } - FileOutputStream output = new FileOutputStream(configFile); - try { - properties.store(output, "Configuration for Collect"); - } finally { - output.close(); - } - } catch (IOException e) { - System.err.println("failed to save configuration to " + configFile); - e.printStackTrace(); - } - } - - - // ------------------------------------------------------------------- - // Serial communication - // ------------------------------------------------------------------- - - public boolean sendToNode(String data) { - if (serialConnection != null && serialConnection.isOpen() && serialConnection.isSerialOutputSupported()) { - serialConsole.addSerialData("SEND: " + data); - serialConnection.writeSerialData(data); - return true; - } - return false; - } - - public void handleIncomingData(long systemTime, String line) { - if (line.length() == 0 || line.charAt(0) == '#') { - // Ignore empty lines, comments, and annotations. - return; - } - SensorData sensorData = SensorData.parseSensorData(this, line, systemTime); - if (sensorData != null) { - // Sensor data received - handleSensorData(sensorData); - return; - } - System.out.println("SERIAL: " + line); - serialConsole.addSerialData(line); - } - - // ------------------------------------------------------------------- - // Node time estimation - // ------------------------------------------------------------------- - - public long getNodeTime() { - return System.currentTimeMillis() + nodeTimeDelta; - } - - private void updateNodeTime(SensorData sensorData) { - this.nodeTimeDelta = sensorData.getNodeTime() - System.currentTimeMillis(); - } - - - // ------------------------------------------------------------------- - // SensorData handling - // ------------------------------------------------------------------- - - public int getSensorDataCount() { - return sensorDataList.size(); - } - - public SensorData getSensorData(int i) { - return sensorDataList.get(i); - } - - private void handleSensorData(final SensorData sensorData) { - System.out.println("SENSOR DATA: " + sensorData); - saveSensorData(sensorData); - if (sensorData.getNode().addSensorData(sensorData)) { - updateNodeTime(sensorData); - sensorDataList.add(sensorData); - handleLinks(sensorData); - if (visualizers != null) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - for (int i = 0, n = visualizers.length; i < n; i++) { - visualizers[i].nodeDataReceived(sensorData); - } - } - }); - } - } - } - - private void handleLinks(SensorData sensorData) { - String nodeID = sensorData.getBestNeighborID(); - if (nodeID != null) { - Node neighbor = addNode(nodeID); - Node source = sensorData.getNode(); - Link link = source.getLink(neighbor); - link.setETX(sensorData.getBestNeighborETX()); - link.setLastActive(sensorData.getNodeTime()); - } - } - - private void initSensorData() { - loadSensorData(SENSORDATA_FILE, true); - } - - private boolean loadSensorData(String filename, boolean isStrict) { - File fp = new File(filename); - if (fp.exists() && fp.canRead()) { - BufferedReader in = null; - try { - in = new BufferedReader(new FileReader(fp)); - String line; - int no = 0; - while ((line = in.readLine()) != null) { - no++; - if (line.length() == 0 || line.charAt(0) == '#') { - // Ignore empty lines and comments - } else { - SensorData data = SensorData.parseSensorData(this, line); - if (data != null) { - if (data.getNode().addSensorData(data)) { - updateNodeTime(data); - sensorDataList.add(data); - handleLinks(data); - } - } else if (isStrict) { - // TODO exit here? - System.err.println("Failed to parse sensor data from log line " + no + ": " + line); - } - } - } - in.close(); - } catch (IOException e) { - System.err.println("Failed to read sensor data log from " + fp.getAbsolutePath()); - e.printStackTrace(); - return false; - } - } - return true; - } - - private void saveSensorData(SensorData data) { - PrintWriter output = this.sensorDataOutput; - if (output == null && isSensorLogUsed) { - try { - output = sensorDataOutput = new PrintWriter(new FileWriter(SENSORDATA_FILE, true)); - } catch (IOException e) { - System.err.println("Failed to add sensor data to log '" + SENSORDATA_FILE + '\''); - e.printStackTrace(); - } - } - if (output != null) { - output.println(data.toString()); - output.flush(); - } - } - - private void clearSensorData() { - sensorDataList.clear(); - Node[] nodes = getNodes(); - this.selectedNodes = null; - nodeList.clearSelection(); - if (nodeModel.size() > 1) { - nodeModel.removeRange(1, nodeModel.size() - 1); - } - this.nodeTable.clear(); - synchronized (this) { - this.nodeCache = null; - } - if (nodes != null) { - for(Node node : nodes) { - node.removeAllSensorData(); - } - } - if (visualizers != null) { - for(Visualizer v : visualizers) { - v.nodesSelected(null); - v.clearNodeData(); - } - } - // Remove any saved node positions - for(String key: configTable.keySet().toArray(new String[0])) { - String property = key.toString(); - if (!property.startsWith("collect")) { - configTable.remove(property); - } - } - } - - private void clearSensorDataLog() { - PrintWriter output = this.sensorDataOutput; - if (output != null) { - output.close(); - } - // Remove the sensor data log - new File(SENSORDATA_FILE).delete(); - this.sensorDataOutput = null; - } - - protected class ConnectSerialAction extends AbstractAction implements Runnable { - - private static final long serialVersionUID = 1L; - - private boolean isRunning; - - public ConnectSerialAction(String name) { - super(name); - } - - public void actionPerformed(ActionEvent e) { - if (!isRunning) { - isRunning = true; - new Thread(this, "serial").start(); - } - } - - public void run() { - try { - if (serialConnection != null) { - if (serialConnection.isOpen()) { - serialConnection.close(); - } else { - connectToSerial(); - } - } else { - JOptionPane.showMessageDialog(window, "No serial connection configured", "Error", JOptionPane.ERROR_MESSAGE); - } - } finally { - isRunning = false; - } - } - - } - - protected class MoteProgramAction extends AbstractAction implements Runnable { - - private static final long serialVersionUID = 1L; - - private boolean isRunning = false; - - public MoteProgramAction(String name) { - super(name); - } - - public void actionPerformed(ActionEvent e) { - if (!isRunning) { - isRunning = true; - new Thread(this, "program thread").start(); - } - } - - @Override - public void run() { - try { - MoteProgrammer mp = new MoteProgrammer(); - mp.setParentComponent(window); - mp.setFirmwareFile(FIRMWARE_FILE); - mp.searchForMotes(); - String[] motes = mp.getMotes(); - if (motes == null || motes.length == 0) { - JOptionPane.showMessageDialog(window, "Could not find any connected nodes", "Error", JOptionPane.ERROR_MESSAGE); - return; - } - int reply = JOptionPane.showConfirmDialog(window, "Found " + motes.length + " connected nodes.\n" - + "Do you want to upload the firmware " + FIRMWARE_FILE + '?'); - if (reply == JFileChooser.APPROVE_OPTION) { - boolean wasOpen = serialConnection != null && serialConnection.isOpen(); - if (serialConnection != null) { - serialConnection.close(); - } - if (wasOpen) { - Thread.sleep(1000); - } - mp.programMotes(); - mp.waitForProcess(); - if (wasOpen) { - connectToSerial(); - } - } - } catch (Exception e) { - e.printStackTrace(); - JOptionPane.showMessageDialog(window, "Programming failed: " + e, "Error", JOptionPane.ERROR_MESSAGE); - } finally { - isRunning = false; - } - } - - } - - - // ------------------------------------------------------------------- - // SerialConnection Listener - // ------------------------------------------------------------------- - - @Override - public void serialData(SerialConnection connection, String line) { - handleIncomingData(System.currentTimeMillis(), line); - } - - @Override - public void serialOpened(SerialConnection connection) { - String connectionName = connection.getConnectionName(); - serialConsole.addSerialData("*** Serial console listening on " + connectionName + " ***"); - hasSerialOpened = true; - if (connection.isMultiplePortsSupported()) { - String comPort = connection.getComPort(); - // Remember the last selected serial port - configTable.put("collect.serialport", comPort); - } - setSystemMessage("connected to " + connectionName); - - if (!connection.isSerialOutputSupported()) { - serialConsole.addSerialData("*** Serial output not supported ***"); - } else if (doSendInitAtStartup) { - // Send any initial commands - doSendInitAtStartup = false; - - if (hasInitScript()) { - // Wait a short time before running the init script - sleep(3000); - - runInitScript(); - } - } - } - - @Override - public void serialClosed(SerialConnection connection) { - String prefix; - if (hasSerialOpened) { - serialConsole.addSerialData("*** Serial connection terminated ***"); - prefix = "Serial connection terminated.\n"; - hasSerialOpened = false; - setSystemMessage("not connected"); - } else { - prefix = "Failed to connect to " + connection.getConnectionName() + '\n'; - } - if (!connection.isClosed()) { - if (connection.isMultiplePortsSupported()) { - String options[] = {"Retry", "Search for connected nodes", "Cancel"}; - int value = JOptionPane.showOptionDialog(window, - prefix + "Do you want to retry or search for connected nodes?", - "Reconnect to serial port?", - JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, - null, options, options[0]); - if (value == JOptionPane.CLOSED_OPTION || value == 2) { -// exit(); - } else { - String comPort = connection.getComPort(); - if (value == 1) { - // Select new serial port - comPort = MoteFinder.selectComPort(window); - if (comPort == null) { -// exit(); - } - } - // Try to open com port again - if (comPort != null) { - connection.open(comPort); - } - } - } else { -// JOptionPane.showMessageDialog(window, -// prefix, "Serial Connection Closed", JOptionPane.ERROR_MESSAGE); - } - } - } - - - // ------------------------------------------------------------------- - // Main - // ------------------------------------------------------------------- - - public static void main(String[] args) { - boolean resetSensorLog = false; - boolean useSensorLog = true; - boolean useSerialOutput = true; - String host = null; - String command = null; - String logFileToLoad = null; - String comPort = null; - int port = -1; - for(int i = 0, n = args.length; i < n; i++) { - String arg = args[i]; - if (arg.length() == 2 && arg.charAt(0) == '-') { - switch (arg.charAt(1)) { - case 'a': - if (i + 1 < n) { - host = args[++i]; - int pIndex = host.indexOf(':'); - if (pIndex > 0) { - port = Integer.parseInt(host.substring(pIndex + 1)); - host = host.substring(0, pIndex); - } - } else { - usage(arg); - } - break; - case 'c': - if (i + 1 < n) { - command = args[++i]; - } else { - usage(arg); - } - break; - case 'p': - if (i + 1 < n) { - port = Integer.parseInt(args[++i]); - } else { - usage(arg); - } - break; - case 'r': - resetSensorLog = true; - break; - case 'n': - useSensorLog = false; - break; - case 'i': - useSerialOutput = false; - break; - case 'f': - command = STDIN_COMMAND; - if (i + 1 < n && !args[i + 1].startsWith("-")) { - logFileToLoad = args[++i]; - } - break; - case 'h': - usage(null); - break; - default: - usage(arg); - break; - } - } else if (comPort == null) { - comPort = arg; - } else { - usage(arg); - } - } - - CollectServer server = new CollectServer(); - SerialConnection serialConnection; - if (host != null) { - if (port <= 0) { - port = 60001; - } - serialConnection = new TCPClientConnection(server, host, port); - } else if (port > 0) { - serialConnection = new UDPConnection(server, port); - } else if (command == null) { - serialConnection = new SerialDumpConnection(server); - } else if (command == STDIN_COMMAND) { - serialConnection = new StdinConnection(server); - } else { - serialConnection = new CommandConnection(server, command); - } - if (comPort == null) { - comPort = server.getConfig("collect.serialport"); - } - if (comPort != null) { - serialConnection.setComPort(comPort); - } - if (!useSerialOutput) { - serialConnection.setSerialOutputSupported(false); - } - - server.isSensorLogUsed = useSensorLog; - if (useSensorLog && resetSensorLog) { - server.clearSensorDataLog(); - } - if (logFileToLoad != null) { - server.loadSensorData(logFileToLoad, false); - } - server.start(serialConnection); - } - - private static void usage(String arg) { - if (arg != null) { - System.err.println("Unknown argument '" + arg + '\''); - } - System.err.println("Usage: java CollectServer [-n] [-i] [-r] [-f [file]] [-a host:port] [-p port] [-c command] [COMPORT]"); - System.err.println(" -n : Do not read or save sensor data log"); - System.err.println(" -r : Clear any existing sensor data log at startup"); - System.err.println(" -i : Do not allow serial output"); - System.err.println(" -f : Read serial data from standard in"); - System.err.println(" -a : Connect to specified host:port"); - System.err.println(" -p : Read data from specified UDP port"); - System.err.println(" -c : Use specified command for serial data input/output"); - System.err.println(" COMPORT: The serial port to connect to"); - System.exit(arg != null ? 1 : 0); - } -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/CommandConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/CommandConnection.java deleted file mode 100644 index dd19761b73068e72b7c409938259cf858b383106..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/CommandConnection.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * CommandConnection - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 5 oct 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; - -/** - * - */ -public class CommandConnection extends SerialConnection { - - protected Process commandProcess; - protected String command; - - public CommandConnection(SerialConnectionListener listener) { - super(listener); - } - - public CommandConnection(SerialConnectionListener listener, String command) { - super(listener); - this.command = command; - } - - @Override - public String getConnectionName() { - return command; - } - - public String getCommand() { - return command; - } - - public void setCommand(String command) { - this.command = command; - } - - @Override - public void open(String comPort) { - close(); - this.comPort = comPort == null ? "" : comPort; - - String fullCommand = getCommand(); - - isClosed = false; - try { - String[] cmd = fullCommand.split(" "); - System.err.println("Running '" + fullCommand + '\''); - - commandProcess = Runtime.getRuntime().exec(cmd); - final BufferedReader input = new BufferedReader(new InputStreamReader(commandProcess.getInputStream())); - final BufferedReader err = new BufferedReader(new InputStreamReader(commandProcess.getErrorStream())); - setSerialOutput(new PrintWriter(new OutputStreamWriter(commandProcess.getOutputStream()))); - - /* Start thread listening on standard out */ - Thread readInput = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = input.readLine()) != null) { - standardData(line); - } - input.close(); - System.err.println("SerialConnection command terminated."); - closeConnection(); - } catch (IOException e) { - lastError = "Error when reading from SerialConnection command: " + e; - System.err.println(lastError); - if (!isClosed) { - e.printStackTrace(); - closeConnection(); - } - } - } - }, "read input stream thread"); - - /* Start thread listening on standard err */ - Thread readError = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = err.readLine()) != null) { - errorData(line); - } - err.close(); - } catch (IOException e) { - if (!isClosed) { - System.err.println("Error when reading from SerialConnection command: " + e); - e.printStackTrace(); - } - } - } - }, "read error stream thread"); - - if (!isOpen) { - isOpen = true; - serialOpened(); - } - readInput.start(); - readError.start(); - } catch (Exception e) { - lastError = "Failed to execute '" + fullCommand + "': " + e; - System.err.println(lastError); - e.printStackTrace(); - closeConnection(); - } - } - - protected void standardData(String line) { - serialData(line); - } - - protected void errorData(String line) { - System.err.println("SerialConnection error stream> " + line); - } - - @Override - protected void doClose() { - if (commandProcess != null) { - commandProcess.destroy(); - commandProcess = null; - } - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/Link.java b/tools/collect-view/src/org/contikios/contiki/collect/Link.java deleted file mode 100644 index 6575801b4ff53b274bd59f8d2888029e146aa398..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/Link.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * Link - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; - -/** - * - */ -public class Link { - - public final Node node; - - private double etx; - private int quality = 100; - private long lastActive = 0L; - - public Link(Node node) { - this.node = node; - this.lastActive = System.currentTimeMillis(); - } - - public Node getNode() { - return node; - } - - public int getQuality() { - return quality; - } - - public void setQuality(int quality) { - this.quality = quality; - } - - public double getETX() { - return etx; - } - - public void setETX(double etx) { - this.etx = etx; - } - - public long getLastActive() { - return lastActive; - } - - public void setLastActive(long time) { - this.lastActive = time; - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/MoteFinder.java b/tools/collect-view/src/org/contikios/contiki/collect/MoteFinder.java deleted file mode 100644 index 2c3c86d5be1ab060493766066355571310aec773..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/MoteFinder.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * Motelist - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 4 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.awt.Component; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.swing.JOptionPane; - -/** - * - */ -public class MoteFinder { - - public static final String MOTELIST_WINDOWS = "./tools/motelist-windows.exe"; - public static final String MOTELIST_LINUX = "./tools/motelist-linux"; - public static final String MOTELIST_MACOS = "./tools/motelist-macos"; - - private final Pattern motePattern; - private final boolean isWindows; - private final boolean isMacos; - private Process moteListProcess; -// private boolean hasVerifiedProcess; - private ArrayList<String> comList = new ArrayList<String>(); - private ArrayList<String> moteList = new ArrayList<String>(); - - public MoteFinder() { - String osName = System.getProperty("os.name", "").toLowerCase(); - isWindows = osName.startsWith("win"); - isMacos = osName.startsWith("mac"); - motePattern = Pattern.compile("\\s(COM|/dev/[a-zA-Z]+|/dev/tty.usbserial-)(\\d+|[A-Z0-9]+)\\s"); - } - - public String[] getMotes() throws IOException { - searchForMotes(); - return getMoteList(); - } - - public String[] getComPorts() throws IOException { - searchForMotes(); - return getComList(); - } - - private void searchForMotes() throws IOException { - comList.clear(); - moteList.clear(); -// hasVerifiedProcess = false; - - /* Connect to COM using external serialdump application */ - String fullCommand; - if (isWindows) { - fullCommand = MOTELIST_WINDOWS; - } else if (isMacos) { - fullCommand = MOTELIST_MACOS; - } else { - fullCommand = MOTELIST_LINUX; - } - - try { - String[] cmd = new String[] { fullCommand }; - moteListProcess = Runtime.getRuntime().exec(cmd); - final BufferedReader input = new BufferedReader(new InputStreamReader(moteListProcess.getInputStream())); - final BufferedReader err = new BufferedReader(new InputStreamReader(moteListProcess.getErrorStream())); - - /* Start thread listening on stdout */ - Thread readInput = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = input.readLine()) != null) { - parseIncomingLine(line); - } - input.close(); - } catch (IOException e) { - System.err.println("Exception when reading from motelist"); - e.printStackTrace(); - } - } - }, "read motelist thread"); - - /* Start thread listening on stderr */ - Thread readError = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = err.readLine()) != null) { - System.err.println("Motelist error stream> " + line); - } - err.close(); - } catch (IOException e) { - System.err.println("Exception when reading from motelist error stream: " + e); - } - } - }, "read motelist error stream thread"); - - readInput.start(); - readError.start(); - - // Wait for the motelist program to finish executing - readInput.join(); - } catch (Exception e) { - throw (IOException) new IOException("Failed to execute '" + fullCommand + "'").initCause(e); - } - } - - private String[] getComList() { - return comList.toArray(new String[comList.size()]); - } - - private String[] getMoteList() { - return moteList.toArray(new String[moteList.size()]); - } - - public void close() { - if (moteListProcess != null) { - moteListProcess.destroy(); - moteListProcess = null; - } - } - - protected void parseIncomingLine(String line) { - if (line.contains("No devices found") || line.startsWith("Reference")) { - // No Sky connected or title before connected motes -// hasVerifiedProcess = true; - } else if (line.startsWith("-------")) { - // Separator - } else { - Matcher matcher = motePattern.matcher(line); - if (matcher.find()) { - String dev = matcher.group(1); - String no = matcher.group(2); - String comPort = dev + no; - String moteID = comPort; - if (isWindows) { - // Special handling of mote id under Windows - int moteNumber = Integer.parseInt(no); - moteID = Integer.toString(moteNumber - 1); - } - comList.add(comPort); - moteList.add(moteID); - } else { - System.err.println("Motelist> " + line); - } - } - } - - public static String selectComPort(Component parent) { - MoteFinder finder = new MoteFinder(); - try { - String[] motes = finder.getComPorts(); - if (motes == null || motes.length == 0) { - JOptionPane.showMessageDialog(parent, "Could not find any connected motes.", "No mote found", JOptionPane.ERROR_MESSAGE); - return null; - } else if (motes.length == 1) { - // Only one node found - return motes[0]; - } else { - // Several motes found - return (String) JOptionPane.showInputDialog( - parent, "Found multiple connected motes. Please select serial port:", - "Select serial port", JOptionPane.QUESTION_MESSAGE, null, motes, motes[0]); - } - } catch (IOException e) { - e.printStackTrace(); - JOptionPane.showMessageDialog(parent, "Failed to search for connected motes:\n" + e, "Error", JOptionPane.ERROR_MESSAGE); - return null; - } finally { - finder.close(); - } - } - - public static void main(String[] args) throws IOException { - MoteFinder finder = new MoteFinder(); - String[] comPorts = args.length > 0 && "-v".equals(args[0]) ? - finder.getMotes() : finder.getComPorts(); - finder.close(); - if (comPorts == null || comPorts.length == 0) { - System.out.println("No motes connected"); - } else { - for(String port: comPorts) { - System.out.println("Found Sky at " + port); - } - } - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammer.java b/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammer.java deleted file mode 100644 index 11809bf46a5004207e3a0bea3597715392f493b2..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammer.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * MoteProgrammer - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 10 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.awt.BorderLayout; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; -import java.io.IOException; -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JPanel; -import javax.swing.JProgressBar; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.SwingUtilities; - -/** - * - */ -public class MoteProgrammer { - - private MoteProgrammerProcess[] processes; - private String[] motes; - private String firmwareFile; - - private Window parent; - private JProgressBar progressBar; - protected JTextArea logTextArea; - protected JDialog dialog; - protected JButton closeButton; - private boolean isDone; - - public MoteProgrammer() { - } - - public Window getParentComponent() { - return parent; - } - - public void setParentComponent(Window parent) { - this.parent = parent; - } - - public boolean hasMotes() { - return motes != null && motes.length > 0; - } - - public String[] getMotes() { - return motes; - } - - public void setMotes(String[] motes) { - this.motes = motes; - } - - public void searchForMotes() throws IOException { - MoteFinder finder = new MoteFinder(); - motes = finder.getMotes(); - finder.close(); - } - - public String getFirmwareFile() { - return firmwareFile; - } - - public void setFirmwareFile(String firmwareFile) { - this.firmwareFile = firmwareFile; - } - - public void programMotes() throws IOException { - if (firmwareFile == null) { - throw new IllegalStateException("no firmware"); - } - if (!hasMotes()) { - throw new IllegalStateException("no motes"); - } - File fp = new File(firmwareFile); - if (!fp.canRead()) { - throw new IllegalStateException("can not read firmware file '" + fp.getAbsolutePath() + '\''); - } - if (parent != null) { - // Use GUI - dialog = new JDialog(parent, "Mote Programmer"); - progressBar = new JProgressBar(0, 100); - progressBar.setValue(0); - progressBar.setString("Programming..."); - progressBar.setStringPainted(true); - progressBar.setIndeterminate(true); - dialog.getContentPane().add(progressBar, BorderLayout.NORTH); - - logTextArea = new JTextArea(28, 80); - logTextArea.setEditable(false); - logTextArea.setLineWrap(true); - dialog.getContentPane().add(new JScrollPane(logTextArea), BorderLayout.CENTER); - JPanel panel = new JPanel(); - closeButton = new JButton("Cancel"); - closeButton.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - MoteProgrammer.this.close(); - } - - }); - panel.add(closeButton); - dialog.getContentPane().add(panel, BorderLayout.SOUTH); - dialog.pack(); - dialog.setLocationRelativeTo(parent); - dialog.setVisible(true); - } - processes = new MoteProgrammerProcess[motes.length]; - isDone = false; - try { - log("Programming " + motes.length + " motes with '" + firmwareFile + '\'', null); - for (int i = 0, n = processes.length; i < n; i++) { - processes[i] = new MoteProgrammerProcess(motes[i], firmwareFile) { - protected void logLine(String line, boolean stderr, Throwable e) { - if (!handleLogLine(this, line, stderr, e)) { - super.logLine(line, stderr, e); - } - } - protected void processEnded() { - handleProcessEnded(this); - } - }; - processes[i].start(); - } - } catch (Exception e) { - throw (IOException) new IOException("Failed to program motes").initCause(e); - } - } - - public synchronized void waitForProcess() throws InterruptedException { - while (!isDone) { - wait(); - } - } - - public void close() { - MoteProgrammerProcess[] processes = this.processes; - if (processes != null) { - this.processes = null; - for (int i = 0, n = processes.length; i < n; i++) { - if (processes[i] != null) { - processes[i].stop(); - } - } - } - if (dialog != null) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - dialog.setVisible(false); - } - }); - } - isDone = true; - synchronized (this) { - notifyAll(); - } - } - - protected void handleProcessEnded(MoteProgrammerProcess process) { - // Another process has finished - log("Mote@" + process.getMoteID() + "> finished" + (process.hasError() ? " with errors": ""), null); - MoteProgrammerProcess[] processes = this.processes; - if (processes != null) { - int running = 0; - int errors = 0; - for(MoteProgrammerProcess p: processes) { - if (p.isRunning()) { - running++; - } else if (p.hasError()) { - errors++; - } - } - if (running == 0) { - // All processes has finished - isDone = true; - final String doneMessage = "Programming finished with " + errors + " errors."; - log(doneMessage, null); - if (closeButton != null) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - progressBar.setValue(100); - progressBar.setIndeterminate(false); - progressBar.setString(doneMessage); - closeButton.setText("Close"); - }}); - } - synchronized (this) { - notifyAll(); - } - } - } - } - - protected boolean handleLogLine(MoteProgrammerProcess moteProgrammerProcess, - String line, boolean stderr, final Throwable e) { - log("Mote@" + moteProgrammerProcess.getMoteID() + "> " + line, e); - return true; - } - - private void log(String line, final Throwable e) { - System.err.println(line); - if (e != null) { - e.printStackTrace(); - line += "\n " + e; - } - final String text = line; - SwingUtilities.invokeLater(new Runnable() { - public void run() { - int len = logTextArea.getDocument().getLength(); - if (len == 0) { - logTextArea.append(text); - } else { - logTextArea.append('\n' + text); - len++; - } - logTextArea.setCaretPosition(len + text.length()); - } - }); - } - - public static void main(String[] args) throws IOException { - MoteProgrammer mp = new MoteProgrammer(); - if (args.length < 1 || args.length > 2) { - System.err.println("Usage: MoteProgrammer <firmware> [mote]"); - System.exit(1); - } - mp.setFirmwareFile(args[0]); - if (args.length == 2) { - mp.setMotes(new String[] { args[1] }); - } else { - mp.searchForMotes(); - } - if (!mp.hasMotes()) { - System.err.println("No motes connected"); - System.exit(1); - } - mp.programMotes(); - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammerProcess.java b/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammerProcess.java deleted file mode 100644 index 1878abc4103280c0acefabd87d8af314ddbda0a3..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammerProcess.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * MoteProgrammerProcess - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 10 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; - -/** - * - */ -public class MoteProgrammerProcess { - - public static final String BSL_WINDOWS = "./tools/msp430-bsl-windows.exe"; - public static final String BSL_LINUX = "./tools/msp430-bsl-linux"; - - private final String moteID; - private final String firmwareFile; - private final String[][] commandSet; - private int retry = 3; - - private Process currentProcess; - private Thread commandThread; - private boolean isRunning; - private boolean hasError; - - public MoteProgrammerProcess(String moteID, String firmwareFile) { - this.moteID = moteID; - this.firmwareFile = firmwareFile; - String osName = System.getProperty("os.name").toLowerCase(); - String bslCommand; - if (osName.startsWith("win")) { - bslCommand = BSL_WINDOWS; - } else { - bslCommand = BSL_LINUX; - } - commandSet = new String[][] { - { bslCommand, "--telosb", "-c", moteID, "-e" }, - { bslCommand, "--telosb", "-c", moteID, "-I", "-p", firmwareFile }, - { bslCommand, "--telosb", "-c", moteID, "-r" } - }; - } - - public String getMoteID() { - return moteID; - } - - public String getFirmwareFile() { - return firmwareFile; - } - - public int getRetry() { - return retry; - } - - public void setRetry(int retry) { - this.retry = retry; - } - - public boolean isRunning() { - return isRunning; - } - - public boolean hasError() { - return hasError; - } - - public void start() { - if (isRunning) { - // Already running - return; - } - isRunning = true; - commandThread = new Thread(new Runnable() { - public void run() { - try { - int count = 0; - do { - if (count > 0) { - logLine("An error occurred. Retrying.", true, null); - } - count++; - hasError = false; - for (int j = 0, m = commandSet.length; j < m && isRunning && !hasError; j++) { - runCommand(commandSet[j]); - Thread.sleep(2000); - } - } while (isRunning && hasError && count < retry); - } catch (Exception e) { - e.printStackTrace(); - } finally { - isRunning = false; - processEnded(); - } - } - }); - commandThread.start(); - } - - public void stop() { - isRunning = false; - Process process = currentProcess; - if (process != null) { - process.destroy(); - } - } - - public void waitForProcess() throws InterruptedException { - if (isRunning && commandThread != null) { - commandThread.join(); - } - } - - protected void processEnded() { - } - - private void runCommand(String[] cmd) throws IOException, InterruptedException { - if (currentProcess != null) { - currentProcess.destroy(); - } - currentProcess = Runtime.getRuntime().exec(cmd); - final BufferedReader input = new BufferedReader(new InputStreamReader(currentProcess.getInputStream())); - final BufferedReader err = new BufferedReader(new InputStreamReader(currentProcess.getErrorStream())); - - /* Start thread listening on stdout */ - Thread readInput = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = input.readLine()) != null) { - handleLine(line, false); - } - input.close(); - } catch (IOException e) { - logLine("Error reading from command", false, e); - } - } - }, "read stdout thread"); - - /* Start thread listening on stderr */ - Thread readError = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = err.readLine()) != null) { - handleLine(line, true); - } - err.close(); - } catch (IOException e) { - logLine("Error reading from command", true, e); - } - } - }, "read stderr thread"); - - readInput.start(); - readError.start(); - - // Wait for the bsl program to finish executing - readInput.join(); - currentProcess = null; - } - - private void handleLine(String line, boolean stderr) { - if (line.toLowerCase().contains("error")) { - hasError = true; - } - logLine(line, stderr, null); - } - - protected void logLine(String line, boolean stderr, Throwable e) { - if (stderr) { - System.err.println("Programmer@" + moteID + "> " + line); - } else { - System.out.println("Programmer@" + moteID + "> " + line); - } - if (e != null) { - e.printStackTrace(); - } - } - - protected String toString(String[] cmd) { - StringBuilder sb = new StringBuilder(); - for (int i = 0, n = cmd.length; i < n; i++) { - if (i > 0) sb.append(' '); - sb.append(cmd[i]); - } - return sb.toString(); - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/Node.java b/tools/collect-view/src/org/contikios/contiki/collect/Node.java deleted file mode 100644 index 8dc934bbd17ec6af28a600e489700c5411c380db..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/Node.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * Node - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.util.ArrayList; -import java.util.Hashtable; - -/** - * - */ -public class Node implements Comparable<Node> { - - private static final boolean SINGLE_LINK = true; - - private SensorDataAggregator sensorDataAggregator; - private ArrayList<SensorData> sensorDataList = new ArrayList<SensorData>(); - private ArrayList<Link> links = new ArrayList<Link>(); - - private final String id; - private final String name; - - private Hashtable<String,Object> objectTable; - - private long lastActive; - - public Node(String nodeID) { - this(nodeID, nodeID); - } - - public Node(String nodeID, String nodeName) { - this.id = nodeID; - this.name = nodeName; - sensorDataAggregator = new SensorDataAggregator(this); - } - - public final String getID() { - return id; - } - - public final String getName() { - return name; - } - - public long getLastActive() { - return lastActive; - } - - public void setLastActive(long lastActive) { - this.lastActive = lastActive; - } - - @Override - public int compareTo(Node o) { - String i1 = id; - String i2 = o.getID(); - // Shorter id first (4.0 before 10.0) - if (i1.length() == i2.length()) { - return i1.compareTo(i2); - } - return i1.length() - i2.length(); - } - - public String toString() { - return name; - } - - - // ------------------------------------------------------------------- - // Attributes - // ------------------------------------------------------------------- - - public Object getAttribute(String key) { - return getAttribute(key, null); - } - - public Object getAttribute(String key, Object defaultValue) { - if (objectTable == null) { - return null; - } - Object val = objectTable.get(key); - return val == null ? defaultValue : val; - } - - public void setAttribute(String key, Object value) { - if (objectTable == null) { - objectTable = new Hashtable<String,Object>(); - } - objectTable.put(key, value); - } - - public void clearAttributes() { - if (objectTable != null) { - objectTable.clear(); - } - } - - - // ------------------------------------------------------------------- - // SensorData - // ------------------------------------------------------------------- - - public SensorDataAggregator getSensorDataAggregator() { - return sensorDataAggregator; - } - - public SensorData[] getAllSensorData() { - return sensorDataList.toArray(new SensorData[sensorDataList.size()]); - } - - public void removeAllSensorData() { - sensorDataList.clear(); - sensorDataAggregator.clear(); - } - - public SensorData getSensorData(int index) { - return sensorDataList.get(index); - } - - public int getSensorDataCount() { - return sensorDataList.size(); - } - - public boolean addSensorData(SensorData data) { - if (sensorDataList.size() > 0) { - SensorData last = sensorDataList.get(sensorDataList.size() - 1); - if (data.getNodeTime() < last.getNodeTime()) { - // Sensor data already added - System.out.println("SensorData: ignoring (time " + (data.getNodeTime() - last.getNodeTime()) - + "msec): " + data); - return false; - } - } - sensorDataList.add(data); - sensorDataAggregator.addSensorData(data); - return true; - } - - - // ------------------------------------------------------------------- - // Links - // ------------------------------------------------------------------- - - public Link getLink(Node node) { - for(Link l: links) { - if (l.node == node) { - return l; - } - } - - // Add new link - Link l = new Link(node); - if (SINGLE_LINK) { - links.clear(); - } - links.add(l); - return l; - } - - public Link getLink(int index) { - return links.get(index); - } - - public int getLinkCount() { - return links.size(); - } - - public void removeLink(Node node) { - for (int i = 0, n = links.size(); i < n; i++) { - Link l = links.get(i); - if (l.node == node) { - links.remove(i); - break; - } - } - } - - public void clearLinks() { - links.clear(); - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SensorData.java b/tools/collect-view/src/org/contikios/contiki/collect/SensorData.java deleted file mode 100644 index 8e3445d58cf54f97a86131b6c6584b84bc264d93..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SensorData.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * SensorData - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2011/01/09 21:06:10 $ - * $Revision: 1.2 $ - */ - -package org.contikios.contiki.collect; -import java.util.Arrays; - -/** - * - */ -public class SensorData implements SensorInfo { - - private final Node node; - private final int[] values; - private final long nodeTime; - private final long systemTime; - private int seqno; - private boolean isDuplicate; - - public SensorData(Node node, int[] values, long systemTime) { - this.node = node; - this.values = values; - this.nodeTime = ((values[TIMESTAMP1] << 16) + values[TIMESTAMP2]) * 1000L; - this.systemTime = systemTime; - this.seqno = values[SEQNO]; - } - - public Node getNode() { - return node; - } - - public String getNodeID() { - return node.getID(); - } - - public boolean isDuplicate() { - return isDuplicate; - } - - public void setDuplicate(boolean isDuplicate) { - this.isDuplicate = isDuplicate; - } - - public int getSeqno() { - return seqno; - } - - public void setSeqno(int seqno) { - this.seqno = seqno; - } - - public int getValue(int index) { - return values[index]; - } - - public int getValueCount() { - return values.length; - } - - public long getNodeTime() { - return nodeTime; - } - - public long getSystemTime() { - return systemTime; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - if (systemTime > 0L) { - sb.append(systemTime).append(' '); - } - for (int i = 0, n = values.length; i < n; i++) { - if (i > 0) sb.append(' '); - sb.append(values[i]); - } - return sb.toString(); - } - - public static SensorData parseSensorData(CollectServer server, String line) { - return parseSensorData(server, line, 0); - } - - public static SensorData parseSensorData(CollectServer server, String line, long systemTime) { - String[] components = line.trim().split("[ \t]+"); - // Check if COOJA log - if (components.length == VALUES_COUNT + 2 && components[1].startsWith("ID:")) { - if (!components[2].equals("" + VALUES_COUNT)) { - // Ignore non sensor data - return null; - } - try { - systemTime = Long.parseLong(components[0]); - components = Arrays.copyOfRange(components, 2, components.length); - } catch (NumberFormatException e) { - // First column does not seem to be system time - } - - } else if (components[0].length() > 8) { - // Sensor data prefixed with system time - try { - systemTime = Long.parseLong(components[0]); - components = Arrays.copyOfRange(components, 1, components.length); - } catch (NumberFormatException e) { - // First column does not seem to be system time - } - } - if (components.length != SensorData.VALUES_COUNT) { - return null; - } - // Sensor data line (probably) - int[] data = parseToInt(components); - if (data == null || data[0] != VALUES_COUNT) { - System.err.println("Failed to parse data line: '" + line + "'"); - return null; - } - String nodeID = mapNodeID(data[NODE_ID]); - Node node = server.addNode(nodeID); - return new SensorData(node, data, systemTime); - } - - public static String mapNodeID(int nodeID) { - return "" + (nodeID & 0xff) + '.' + ((nodeID >> 8) & 0xff); - } - - private static int[] parseToInt(String[] text) { - try { - int[] data = new int[text.length]; - for (int i = 0, n = data.length; i < n; i++) { - data[i] = Integer.parseInt(text[i]); - } - return data; - } catch (NumberFormatException e) { - return null; - } - } - - public double getCPUPower() { - return (values[TIME_CPU] * POWER_CPU) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getLPMPower() { - return (values[TIME_LPM] * POWER_LPM) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getListenPower() { - return (values[TIME_LISTEN] * POWER_LISTEN) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getTransmitPower() { - return (values[TIME_TRANSMIT] * POWER_TRANSMIT) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getAveragePower() { - return (values[TIME_CPU] * POWER_CPU + values[TIME_LPM] * POWER_LPM - + values[TIME_LISTEN] * POWER_LISTEN + values[TIME_TRANSMIT] * POWER_TRANSMIT) - / (values[TIME_CPU] + values[TIME_LPM]); - } - - public long getPowerMeasureTime() { - return (1000L * (values[TIME_CPU] + values[TIME_LPM])) / TICKS_PER_SECOND; - } - - public double getTemperature() { - return -39.6 + 0.01 * values[TEMPERATURE]; - } - - public double getBatteryVoltage() { - return values[BATTERY_VOLTAGE] * 2 * 2.5 / 4096.0; - } - - public double getBatteryIndicator() { - return values[BATTERY_INDICATOR]; - } - - public double getRadioIntensity() { - return values[RSSI]; - } - - public double getLatency() { - return values[LATENCY] / 32678.0; - } - - public double getHumidity() { - double v = -4.0 + 405.0 * values[HUMIDITY] / 10000.0; - if(v > 100) { - return 100; - } - return v; - } - - public double getLight1() { - return 10.0 * values[LIGHT1] / 7.0; - } - - public double getLight2() { - return 46.0 * values[LIGHT2] / 10.0; - } - - public String getBestNeighborID() { - return values[BEST_NEIGHBOR] > 0 ? mapNodeID(values[BEST_NEIGHBOR]): null; - } - - public double getBestNeighborETX() { - return values[BEST_NEIGHBOR_ETX] / 8.0; - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SensorDataAggregator.java b/tools/collect-view/src/org/contikios/contiki/collect/SensorDataAggregator.java deleted file mode 100644 index a8bfc2a95c81686c371642718b45ddae051de31d..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SensorDataAggregator.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * SensorDataAggregator - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 20 aug 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; - -/** - * - */ -public class SensorDataAggregator implements SensorInfo { - - private final Node node; - private long[] values; - private int minSeqno = Integer.MAX_VALUE; - private int maxSeqno = Integer.MIN_VALUE; - private int seqnoDelta = 0; - private int dataCount; - private int duplicates = 0; - private int lost = 0; - private int nodeRestartCount = 0; - private int nextHopChangeCount = 0; - private int lastNextHop = -1; - private long shortestPeriod = Long.MAX_VALUE; - private long longestPeriod = 0; - - public SensorDataAggregator(Node node) { - this.node = node; - this.values = new long[VALUES_COUNT]; - } - - public Node getNode() { - return node; - } - - public String getNodeID() { - return node.getID(); - } - - public long getValue(int index) { - return values[index]; - } - - public double getAverageValue(int index) { - return dataCount > 0 ? (double)values[index] / (double)dataCount : 0; - } - - public int getValueCount() { - return values.length; - } - - public int getDataCount() { - return dataCount; - } - - public void addSensorData(SensorData data) { - int seqn = data.getValue(SEQNO); - int s = seqn + seqnoDelta; - - int bestNeighbor = data.getValue(BEST_NEIGHBOR); - if (lastNextHop != bestNeighbor && lastNextHop >= 0) { - nextHopChangeCount++; - } - lastNextHop = bestNeighbor; - - if (s <= maxSeqno) { - // Check for duplicates among the last 5 packets - for(int n = node.getSensorDataCount() - 1, i = n > 5 ? n - 5 : 0; i < n; i++) { - SensorData sd = node.getSensorData(i); - if (sd.getValue(SEQNO) != seqn || sd == data || sd.getValueCount() != data.getValueCount()) { - // Not a duplicate - } else if (Math.abs(data.getNodeTime() - sd.getNodeTime()) > 180000) { - // Too long time between packets. Not a duplicate. -// System.err.println("Too long time between packets with same seqno from " -// + data.getNode() + ": " -// + (Math.abs(data.getNodeTime() - sd.getNodeTime()) / 1000) -// + " sec, " + (n - i) + " packets ago"); - } else { - data.setDuplicate(true); - - // Verify that the packet is a duplicate - for(int j = DATA_LEN2, m = data.getValueCount(); j < m; j++) { - if (sd.getValue(j) != data.getValue(j)) { - data.setDuplicate(false); -// System.out.println("NOT Duplicate: " + data.getNode() + " (" -// + (n - i) + ": " -// + ((data.getNodeTime() - sd.getNodeTime()) / 1000) + "sek): " -// + seqn + " value[" + j + "]: " + sd.getValue(j) + " != " -// + data.getValue(j)); - break; - } - } - if (data.isDuplicate()) { -// System.out.println("Duplicate: " + data.getNode() + ": " + seqn -// + ": " -// + (Math.abs(data.getNodeTime() - sd.getNodeTime()) / 1000) -// + " sec, " + (n - i) + " packets ago"); - duplicates++; - break; - } - } - } - } - - if (!data.isDuplicate()) { - for (int i = 0, n = Math.min(VALUES_COUNT, data.getValueCount()); i < n; i++) { - values[i] += data.getValue(i); - } - - if (node.getSensorDataCount() > 1) { - long timeDiff = data.getNodeTime() - node.getSensorData(node.getSensorDataCount() - 2).getNodeTime(); - if (timeDiff > longestPeriod) { - longestPeriod = timeDiff; - } - if (timeDiff < shortestPeriod) { - shortestPeriod = timeDiff; - } - } - if (dataCount == 0) { - // First packet from node. - } else if (maxSeqno - s > 2) { - // Handle sequence number overflow. - seqnoDelta = maxSeqno + 1; - s = seqnoDelta + seqn; - if (seqn > 127) { - // Sequence number restarted at 128 (to separate node restarts - // from sequence number overflow). - seqn -= 128; - seqnoDelta -= 128; - s -= 128; - } else { - // Sequence number restarted at 0. This is usually an indication that - // the node restarted. - nodeRestartCount++; - } - if (seqn > 0) { - lost += seqn; - } - } else if (s > maxSeqno + 1){ - lost += s - (maxSeqno + 1); - } - if (s < minSeqno) minSeqno = s; - if (s > maxSeqno) maxSeqno = s; - dataCount++; - } - data.setSeqno(s); - } - - public void clear() { - for (int i = 0, n = values.length; i < n; i++) { - values[i] = 0L; - } - dataCount = 0; - duplicates = 0; - lost = 0; - nodeRestartCount = 0; - nextHopChangeCount = 0; - lastNextHop = 0; - minSeqno = Integer.MAX_VALUE; - maxSeqno = Integer.MIN_VALUE; - seqnoDelta = 0; - shortestPeriod = Long.MAX_VALUE; - longestPeriod = 0; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - for (int i = 0, n = values.length; i < n; i++) { - if (i > 0) sb.append(' '); - sb.append(values[i]); - } - return sb.toString(); - } - - public double getCPUPower() { - return (values[TIME_CPU] * POWER_CPU) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getLPMPower() { - return (values[TIME_LPM] * POWER_LPM) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getListenPower() { - return (values[TIME_LISTEN] * POWER_LISTEN) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getTransmitPower() { - return (values[TIME_TRANSMIT] * POWER_TRANSMIT) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getAveragePower() { - return (values[TIME_CPU] * POWER_CPU + values[TIME_LPM] * POWER_LPM - + values[TIME_LISTEN] * POWER_LISTEN + values[TIME_TRANSMIT] * POWER_TRANSMIT) - / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getAverageDutyCycle(int index) { - return (double)(values[index]) / (double)(values[TIME_CPU] + values[TIME_LPM]); - } - - public long getPowerMeasureTime() { - return (1000L * (values[TIME_CPU] + values[TIME_LPM])) / TICKS_PER_SECOND; - } - - public double getAverageTemperature() { - return dataCount > 0 ? (-39.6 + 0.01 * (values[TEMPERATURE] / dataCount)) : 0.0; - } - - public double getAverageRtmetric() { - return getAverageValue(RTMETRIC); - } - - public double getAverageRadioIntensity() { - return getAverageValue(RSSI); - } - - public double getAverageLatency() { - return getAverageValue(LATENCY) / 4096.0; - } - - public double getAverageHumidity() { - double v = 0.0; - if (dataCount > 0) { - v = -4.0 + 405.0 * (values[HUMIDITY] / dataCount) / 10000.0; - } - return v > 100 ? 100 : v; - } - - public double getAverageLight1() { - return 10.0 * getAverageValue(LIGHT1) / 7.0; - } - - public double getAverageLight2() { - return 46.0 * getAverageValue(LIGHT2) / 10.0; - } - - public double getAverageBestNeighborETX() { - return getAverageValue(BEST_NEIGHBOR_ETX) / 8.0; - } - - public int getPacketCount() { - return node.getSensorDataCount(); - } - - public int getNextHopChangeCount() { - return nextHopChangeCount; - } - - public int getEstimatedRestarts() { - return nodeRestartCount; - } - - public int getEstimatedLostCount() { - return lost; - } - - public int getDuplicateCount() { - return duplicates; - } - - public int getMinSeqno() { - return minSeqno; - } - - public int getMaxSeqno() { - return maxSeqno; - } - - public long getAveragePeriod() { - if (dataCount > 1) { - long first = node.getSensorData(0).getNodeTime(); - long last = node.getSensorData(node.getSensorDataCount() - 1).getNodeTime(); - return (last - first) / dataCount; - } - return 0; - } - - public long getShortestPeriod() { - return shortestPeriod < Long.MAX_VALUE ? shortestPeriod : 0; - } - - public long getLongestPeriod() { - return longestPeriod; - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SensorInfo.java b/tools/collect-view/src/org/contikios/contiki/collect/SensorInfo.java deleted file mode 100644 index 51043d1c3680de7917f65fd5c7b686978030a75c..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SensorInfo.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * SensorInfo - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 20 aug 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; - - -/** - * - */ -public interface SensorInfo { - - public static final long TICKS_PER_SECOND = 4096L; - public static final double VOLTAGE = 3; - public static final double POWER_CPU = 1.800 * VOLTAGE; /* mW */ - public static final double POWER_LPM = 0.0545 * VOLTAGE; /* mW */ - public static final double POWER_TRANSMIT = 17.7 * VOLTAGE; /* mW */ - public static final double POWER_LISTEN = 20.0 * VOLTAGE; /* mW */ - - public static final int DATA_LEN = 0; - public static final int TIMESTAMP1 = 1; - public static final int TIMESTAMP2 = 2; - public static final int TIMESYNCTIMESTAMP = 3; - public static final int NODE_ID = 4; - public static final int SEQNO = 5; - public static final int HOPS = 6; - public static final int LATENCY = 7; - public static final int DATA_LEN2 = 8; - public static final int CLOCK = 9; - public static final int TIMESYNCHTIME = 10; - public static final int TIME_CPU = 11; - public static final int TIME_LPM = 12; - public static final int TIME_TRANSMIT = 13; - public static final int TIME_LISTEN = 14; - public static final int BEST_NEIGHBOR = 15; - public static final int BEST_NEIGHBOR_ETX = 16; - public static final int RTMETRIC = 17; - public static final int NUM_NEIGHBORS = 18; - public static final int BEACON_INTERVAL = 19; - public static final int BATTERY_VOLTAGE = 20; - public static final int BATTERY_INDICATOR = 21; - public static final int LIGHT1 = 22; - public static final int LIGHT2 = 23; - public static final int TEMPERATURE = 24; - public static final int HUMIDITY = 25; - public static final int RSSI = 26; - - public static final int VALUES_COUNT = 30; - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SerialConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/SerialConnection.java deleted file mode 100644 index c2d140a0310f7493ede2e366266174b79d1fc81e..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SerialConnection.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * SerialConnection - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 5 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.io.PrintWriter; - -/** - * - */ -public abstract class SerialConnection { - - protected final SerialConnectionListener listener; - - protected boolean isSerialOutputSupported = true; - - protected String comPort; - protected boolean isOpen; - protected boolean isClosed = true; - protected String lastError; - - protected PrintWriter serialOutput; - - protected SerialConnection(SerialConnectionListener listener) { - this.listener = listener; - } - - public boolean isMultiplePortsSupported() { - return false; - } - - public void setSerialOutputSupported(boolean isSerialOutputSupported) { - this.isSerialOutputSupported = isSerialOutputSupported; - } - - public boolean isSerialOutputSupported() { - return isSerialOutputSupported; - } - - public boolean isOpen() { - return isOpen; - } - - public boolean isClosed() { - return isClosed; - } - - public abstract String getConnectionName(); - - public String getComPort() { - return comPort; - } - - public void setComPort(String comPort) { - this.comPort = comPort; - } - - public String getLastError() { - return lastError; - } - - protected PrintWriter getSerialOutput() { - return serialOutput; - } - - protected void setSerialOutput(PrintWriter serialOutput) { - this.serialOutput = serialOutput; - } - - public void writeSerialData(String data) { - PrintWriter serialOutput = this.serialOutput; - if (serialOutput != null) { - serialOutput.println(data); - serialOutput.flush(); - } - } - - public abstract void open(String comPort); - - public final void close() { - isClosed = true; - lastError = null; - closeConnection(); - } - - protected final void closeConnection() { - isOpen = false; - if (serialOutput != null) { - serialOutput.close(); - serialOutput = null; - } - doClose(); - serialClosed(); - } - - protected abstract void doClose(); - - protected final void serialData(String line) { - listener.serialData(this, line); - } - - protected final void serialOpened() { - listener.serialOpened(this); - } - - protected final void serialClosed() { - listener.serialClosed(this); - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SerialConnectionListener.java b/tools/collect-view/src/org/contikios/contiki/collect/SerialConnectionListener.java deleted file mode 100644 index 5e266c6e1184a9d9773e7ed9b3d1b4d5dbcaa076..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SerialConnectionListener.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * SerialConnectionListener - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 5 oct 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ -package org.contikios.contiki.collect; - -public interface SerialConnectionListener { - - public void serialData(SerialConnection connection, String line); - - public void serialOpened(SerialConnection connection); - - public void serialClosed(SerialConnection connection); - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SerialDumpConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/SerialDumpConnection.java deleted file mode 100644 index c624ea64acb8611b983b485f0e16cc0e89b965d1..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SerialDumpConnection.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * SerialDumpConnection - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 5 oct 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; - -/** - * - */ -public class SerialDumpConnection extends CommandConnection { - - public static final String SERIALDUMP_WINDOWS = "./tools/serialdump-windows.exe"; - public static final String SERIALDUMP_LINUX = "./tools/serialdump-linux"; - public static final String SERIALDUMP_MACOS = "./tools/serialdump-macos"; - - public SerialDumpConnection(SerialConnectionListener listener) { - super(listener); - } - - @Override - public boolean isMultiplePortsSupported() { - return true; - } - - @Override - public String getConnectionName() { - return comPort; - } - - @Override - public void open(String comPort) { - if (comPort == null) { - throw new IllegalStateException("no com port"); - } - - /* Connect to COM using external serialdump application */ - String osName = System.getProperty("os.name").toLowerCase(); - String fullCommand; - if (osName.startsWith("win")) { - fullCommand = SERIALDUMP_WINDOWS + " " + "-b115200" + " " + getMappedComPortForWindows(comPort); - } else if (osName.startsWith("mac")) { - fullCommand = SERIALDUMP_MACOS + " " + "-b115200" + " " + comPort; - } else { - fullCommand = SERIALDUMP_LINUX + " " + "-b115200" + " " + comPort; - } - setCommand(fullCommand); - super.open(comPort); - } - - @Override - protected void standardData(String line) { - serialData(line); - } - - @Override - protected void errorData(String line) { - if (!isOpen && line.startsWith("connecting") && line.endsWith("[OK]")) { - isOpen = true; - serialOpened(); - } else { - super.errorData(line); - } - } - - private String getMappedComPortForWindows(String comPort) { - if (comPort.startsWith("COM")) { - comPort = "/dev/com" + comPort.substring(3); - } - return comPort; - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/StdinConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/StdinConnection.java deleted file mode 100644 index 337a01a296e9bb259d70340d7615063a5eeadb4a..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/StdinConnection.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * StdinConnection - * - * Authors : Niclas Finne - * Created : 5 oct 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; - -/** - * - */ -public class StdinConnection extends SerialConnection { - - private PrintWriter stdout; - - public StdinConnection(SerialConnectionListener listener) { - super(listener); - // Redirect standard out as standard err to use standard out for serial output - stdout = new PrintWriter(new OutputStreamWriter(System.out)); - System.setOut(System.err); - } - - @Override - public String getConnectionName() { - return "<stdin>"; - } - - @Override - public void open(String comPort) { - close(); - this.comPort = comPort == null ? "" : comPort; - - isClosed = false; - try { - final BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); - setSerialOutput(stdout); - - /* Start thread listening on standard in */ - Thread readInput = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = input.readLine()) != null) { - serialData(line); - // Do not send data too fast - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - input.close(); - System.out.println("SerialConnection stdin terminated."); - closeConnection(); - } catch (IOException e) { - lastError = "Error when reading from SerialConnection stdin: " + e; - System.err.println(lastError); - if (!isClosed) { - e.printStackTrace(); - closeConnection(); - } - } - } - }, "read input stream thread"); - - isOpen = true; - serialOpened(); - readInput.start(); - - } catch (Exception e) { - lastError = "Failed to open stdin for reading: " + e; - System.err.println(lastError); - e.printStackTrace(); - closeConnection(); - } - } - - @Override - protected void doClose() { - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/TCPClientConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/TCPClientConnection.java deleted file mode 100644 index 6a04f8b6512a5012ad6eb6996b318c783cb35e7e..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/TCPClientConnection.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2012, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * ----------------------------------------------------------------- - * - * TCPClientConnection - * - * Authors : Niclas Finne - */ - -package org.contikios.contiki.collect; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintStream; -import java.net.Socket; - -/** - * - */ -public class TCPClientConnection extends SerialConnection { - - private final String host; - private final int port; - - private Socket client; - private BufferedReader in; - private PrintStream out; - - public TCPClientConnection(SerialConnectionListener listener, String host, int port) { - super(listener); - this.host = host; - this.port = port; - } - - @Override - public String getConnectionName() { - return "<tcp://" + host + ':' + port + '>'; - } - - @Override - public void open(String comPort) { - close(); - this.comPort = comPort == null ? "" : comPort; - - isClosed = false; - try { - client = new Socket(host, port); - in = new BufferedReader(new InputStreamReader(client.getInputStream())); - out = new PrintStream(client.getOutputStream()); - System.out.println("Opened TCP connection to " + host + ':' + port); - /* Start thread listening on UDP */ - Thread readInput = new Thread(new Runnable() { - public void run() { - try { - String line; - while (isOpen && (line = in.readLine()) != null) { - serialData(line); - } - } catch (IOException e) { - lastError = "Error when reading from SerialConnection TCP: " + e; - System.err.println(lastError); - if (!isClosed) { - e.printStackTrace(); - closeConnection(); - } - } finally { - System.out.println("SerialConnection TCP terminated."); - closeConnection(); - } - } - }, "TCP thread"); - isOpen = true; - serialOpened(); - readInput.start(); - - } catch (Exception e) { - lastError = "Failed to open TCP connection to " + host + ':' + port + ": " + e; - System.err.println(lastError); - e.printStackTrace(); - closeConnection(); - } - } - - @Override - protected void doClose() { - try { - if (in != null) { - in.close(); - in = null; - } - if (out != null) { - out.close(); - out = null; - } - if (client != null) { - client.close(); - client = null; - } - } catch (IOException e) { - e.printStackTrace(); - } - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/UDPConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/UDPConnection.java deleted file mode 100644 index ae1ed52a945ca0ef57beeb7a119c7fc586bc091c..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/UDPConnection.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2011, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * ----------------------------------------------------------------- - * - * UDPConnection - * - * Authors : Niclas Finne - * Created : 1 June 2011 - */ - -package org.contikios.contiki.collect; - -import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.io.*; -/** - * - */ -public class UDPConnection extends SerialConnection { - - private final int port; -private DatagramSocket serverSocket; - - public UDPConnection(SerialConnectionListener listener, int port) { - super(listener); - this.port = port; - } - - @Override - public String getConnectionName() { - return "<UDP:" + port + ">"; - } - - @Override - public void open(String comPort) { - close(); - this.comPort = comPort == null ? "" : comPort; - - isClosed = false; - try { - serverSocket = new DatagramSocket(port); - System.out.println("Opened UDP port: " + port); - /* Start thread listening on UDP */ - Thread readInput = new Thread(new Runnable() { - public void run() { - byte[] data = new byte[1024]; - try { - while (isOpen) { - DatagramPacket packet = new DatagramPacket(data, data.length); - serverSocket.receive(packet); - - InetAddress addr = packet.getAddress(); - System.out.println("UDP: received " + packet.getLength() + " bytes from " + addr.getHostAddress() + ":" + packet.getPort()); - - StringWriter strOut = new StringWriter(); - PrintWriter out = new PrintWriter(strOut); - int payloadLen = packet.getLength() - 2; - out.printf("%d", 8 + payloadLen / 2); - /* Timestamp. Ignore time synch for now. */ - long time = System.currentTimeMillis() / 1000; - out.printf(" %d %d 0", - ((time >> 16) & 0xffff), time & 0xffff); - byte[] payload = packet.getData(); - int seqno = payload[0] & 0xff; - int hops = 0; /* how to get TTL / hot limit in Java??? */ - byte[] address = addr.getAddress(); - /* Ignore latency for now */ - out.printf(" %d %d %d %d", - ((address[14] & 0xff) + - ((address[15] & 0xff) << 8))&0xffff, seqno, hops, 0); - int d = 0; - for(int i = 0; i < payloadLen ; i += 2) { - d = (payload[i + 2] & 0xff) + ((payload[i + 3] & 0xff) << 8); - out.printf(" %d", d & 0xffff); - } - - String line = strOut.toString(); - serialData(line); - } - System.out.println("SerialConnection UDP terminated."); - closeConnection(); - } catch (IOException e) { - lastError = "Error when reading from SerialConnection UDP: " + e; - System.err.println(lastError); - if (!isClosed) { - e.printStackTrace(); - closeConnection(); - } - } - } - }, "UDP thread"); - isOpen = true; - serialOpened(); - readInput.start(); - - } catch (Exception e) { - lastError = "Failed to open UDP server at port " + port + ": " + e; - System.err.println(lastError); - e.printStackTrace(); - closeConnection(); - } - } - - @Override - protected void doClose() { - if (serverSocket != null) { - serverSocket.close(); - serverSocket = null; - } - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/Visualizer.java b/tools/collect-view/src/org/contikios/contiki/collect/Visualizer.java deleted file mode 100644 index ea111795abead79342f54172cc27c5654fd8853b..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/Visualizer.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * Visualizer - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; - -import java.awt.Component; - -/** - * - */ -public interface Visualizer { - - public String getCategory(); - public String getTitle(); - public Component getPanel(); - public void nodesSelected(Node[] node); - public void nodeAdded(Node node); - public void nodeDataReceived(SensorData sensorData); - public void clearNodeData(); - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/AggregatedTimeChartPanel.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/AggregatedTimeChartPanel.java deleted file mode 100644 index f898e0e6ab66bf9ac98951fda925963401fac776..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/AggregatedTimeChartPanel.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * ----------------------------------------------------------------- - * - * PacketChartPanel - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 6 sep 2010 - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Dimension; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -import javax.swing.JPanel; - -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; -import org.jfree.data.time.Minute; -import org.jfree.data.time.TimeSeries; -import org.jfree.data.time.TimeSeriesCollection; - -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public abstract class AggregatedTimeChartPanel<T> extends JPanel implements Visualizer { - - private static final long serialVersionUID = 2100788758213434540L; - - protected final CollectServer server; - protected final String category; - protected final String title; - protected final TimeSeries series; - - protected final JFreeChart chart; - protected final ChartPanel chartPanel; - - private Node[] selectedNodes; - private HashMap<Node,T> selectedMap = new HashMap<Node,T>(); - - public AggregatedTimeChartPanel(CollectServer server, String category, String title, - String timeAxisLabel, String valueAxisLabel) { - super(new BorderLayout()); - this.server = server; - this.category = category; - this.title = title; - this.series = new TimeSeries(title, Minute.class); - TimeSeriesCollection timeSeries = new TimeSeriesCollection(series); - this.chart = ChartFactory.createTimeSeriesChart( - title, timeAxisLabel, valueAxisLabel, timeSeries, - false, true, false - ); - this.chartPanel = new ChartPanel(chart); - this.chartPanel.setPreferredSize(new Dimension(500, 270)); - setBaseShapeVisible(false); - add(chartPanel, BorderLayout.CENTER); - } - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return title; - } - - @Override - public Component getPanel() { - return this; - } - - @Override - public void nodeAdded(Node node) { - // Ignore - } - - @Override - public void nodesSelected(Node[] nodes) { - if (isVisible()) { - updateSelected(nodes); - } - } - - private void updateSelected(Node[] nodes) { - if (this.selectedNodes != nodes) { - this.selectedNodes = nodes; - this.selectedMap.clear(); - if (nodes != null) { - for(Node node : nodes) { - this.selectedMap.put(node, createState(node)); - } - } - updateCharts(); - } - } - - @Override - public void nodeDataReceived(SensorData data) { - if (isVisible() && selectedMap.get(data.getNode()) != null) { - updateCharts(); - } - } - - @Override - public void clearNodeData() { - if (isVisible()) { - updateCharts(); - } - } - - private void updateCharts() { - int duplicates = 0; - int total = 0; - series.clear(); - if (this.selectedNodes != null && server.getSensorDataCount() > 0) { - long minute = server.getSensorData(0).getNodeTime() / 60000; - long lastMinute = minute; - int count = 0; - clearState(selectedMap); - for(int i = 0; i < server.getSensorDataCount(); i++) { - SensorData sd = server.getSensorData(i); - T nodeState = selectedMap.get(sd.getNode()); - if (nodeState != null) { - if (sd.isDuplicate()) { - duplicates++; - } else { - long min = sd.getNodeTime() / 60000; - if (min != minute) { - if (lastMinute < minute) { - series.add(new Minute(new Date(lastMinute * 60000L)), 0); - if (lastMinute < minute - 1) { - series.add(new Minute(new Date((minute - 1) * 60000L)), 0); - } - } - series.add(new Minute(new Date(minute * 60000L)), getTotalDataValue(count)); - count = 0; - lastMinute = minute + 1; - minute = min; - } - count += getSensorDataValue(sd, nodeState); - } - total++; - } - } - } - chart.setTitle(getTitle(selectedMap.size(), total, duplicates)); - } - - protected String getTitle(int nodeCount, int dataCount, int duplicateCount) { - return title; - } - - protected abstract T createState(Node node); - - protected void clearState(Map<Node,T> map) { - } - - protected int getTotalDataValue(int value) { - return value; - } - - protected abstract int getSensorDataValue(SensorData sd, T nodeState); - - public boolean getBaseShapeVisible() { - return ((XYLineAndShapeRenderer)this.chart.getXYPlot().getRenderer()).getBaseShapesVisible(); - } - - public void setBaseShapeVisible(boolean visible) { - ((XYLineAndShapeRenderer)this.chart.getXYPlot().getRenderer()).setBaseShapesVisible(visible); - } - - public double getRangeMinimumSize() { - return chart.getXYPlot().getRangeAxis().getAutoRangeMinimumSize(); - } - - public void setRangeMinimumSize(double size) { - chart.getXYPlot().getRangeAxis().setAutoRangeMinimumSize(size); - } - - public void setVisible(boolean visible) { - updateSelected(visible ? server.getSelectedNodes() : null); - super.setVisible(visible); - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/BarChartPanel.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/BarChartPanel.java deleted file mode 100644 index cb6969331d6e3d1de88909aeb085f438337f3dca..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/BarChartPanel.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * PowerPanel - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 5 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.GradientPaint; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import javax.swing.JPanel; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.plot.CategoryPlot; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.renderer.category.BarRenderer; -import org.jfree.data.category.DefaultCategoryDataset; -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public abstract class BarChartPanel extends JPanel implements Visualizer { - - private static final long serialVersionUID = 7664283678708048061L; - - protected final CollectServer server; - protected final String category; - protected final String title; - protected final String[] categories; - protected final JFreeChart chart; - protected final ChartPanel chartPanel; - protected final DefaultCategoryDataset dataset; - - private boolean isShowingAllNodes = false; - private int categoryOrder = 0; - - protected BarChartPanel(CollectServer server, String category, String title, - String chartTitle, String domainAxisLabel, String valueAxisLabel, - String[] categories) { - this(server, category, title, chartTitle, domainAxisLabel, valueAxisLabel, categories, true); - } - - protected BarChartPanel(CollectServer server, String category, String title, - String chartTitle, String domainAxisLabel, String valueAxisLabel, - String[] categories, boolean stackedChart) { - super(new BorderLayout()); - this.server = server; - this.category = category; - this.title = title; - this.categories = categories; - - /* Create chart with power of all nodes */ - dataset = new DefaultCategoryDataset(); - if (stackedChart) { - this.chart = ChartFactory.createStackedBarChart(chartTitle, - domainAxisLabel, valueAxisLabel, dataset, PlotOrientation.VERTICAL, - categories.length > 1, true, false); - } else { - this.chart = ChartFactory.createBarChart(chartTitle, - domainAxisLabel, valueAxisLabel, dataset, PlotOrientation.VERTICAL, - categories.length > 1, true, false); - if (categories.length > 1) { - CategoryPlot plot = chart.getCategoryPlot(); - BarRenderer renderer = (BarRenderer) plot.getRenderer(); - renderer.setItemMargin(0); - } - } - this.chartPanel = new ChartPanel(chart, false); - this.chartPanel.setPreferredSize(new Dimension(500, 270)); - if (categories.length > 1) { - this.chartPanel.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - categoryOrder++; - updateCharts(); - } - }); - } - - CategoryPlot plot = (CategoryPlot) chart.getPlot(); - BarRenderer renderer = (BarRenderer) plot.getRenderer(); - if (categories.length < 3) { - renderer.setDrawBarOutline(false); - - GradientPaint gp = new GradientPaint(0.0f, 0.0f, Color.RED, - 0.0f, 0.0f, new Color(128, 0, 0)); - renderer.setSeriesPaint(0, gp); - if (categories.length > 1) { - gp = new GradientPaint(0.0f, 0.0f, Color.BLUE, - 0.0f, 0.0f, new Color(0, 0, 128)); - renderer.setSeriesPaint(1, gp); - } - } else { - renderer.setDrawBarOutline(true); - } - - add(chartPanel, BorderLayout.CENTER); - } - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return title; - } - - @Override - public Component getPanel() { - return this; - } - - public boolean isShowingAllNodes() { - return isShowingAllNodes; - } - - public void setShowingAllNodes(boolean isShowingAllNodes) { - if (this.isShowingAllNodes != isShowingAllNodes) { - this.isShowingAllNodes = isShowingAllNodes; - if (isVisible()) { - updateCharts(); - } - } - } - - @Override - public void nodeAdded(Node node) { - if (isVisible()) { - int count = node.getSensorDataCount(); - if (count > 0 || isShowingAllNodes) { - addNode(node); - } - if (count > 0) { - addSensorData(node.getSensorData(count - 1)); - } - } - } - - @Override - public void nodesSelected(Node[] nodes) { - } - - @Override - public void nodeDataReceived(SensorData data) { - if (isVisible()) { - addSensorData(data); - } - } - - @Override - public void clearNodeData() { - if (isVisible()) { - updateCharts(); - } - } - - private void updateCharts() { - dataset.clear(); - Node[] nodes = server.getNodes(); - if (nodes != null) { - for (int i = 0, n = nodes.length; i < n; i++) { - int count = nodes[i].getSensorDataCount(); - if (count > 0 || isShowingAllNodes) { - addNode(nodes[i]); - } - if (count > 0) { - addSensorData(nodes[i].getSensorData(count - 1)); - } - } - } - } - - private void addNode(Node node) { - String name = node.getName(); - for (int j = 0, m = categories.length; j < m; j++) { - dataset.addValue(0, categories[(j + categoryOrder) % categories.length], name); - } - } - - public void setVisible(boolean visible) { - if (visible) { - updateCharts(); - } else { - dataset.clear(); - } - super.setVisible(visible); - } - - protected abstract void addSensorData(SensorData data); - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/MapPanel.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/MapPanel.java deleted file mode 100644 index 5a6652b9447a8469edca3140316fa5c36b3e943b..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/MapPanel.java +++ /dev/null @@ -1,851 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * MapPanel - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2010/11/23 16:21:48 $ - * $Revision: 1.4 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.Color; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridLayout; -import java.awt.Polygon; -import java.awt.RenderingHints; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.ArrayList; -import java.util.Hashtable; -import java.util.Properties; -import java.util.logging.Logger; - -import javax.swing.BorderFactory; -import javax.swing.ImageIcon; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JFormattedTextField; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JSlider; -import javax.swing.Timer; -import javax.swing.border.LineBorder; -import javax.swing.border.TitledBorder; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.plaf.basic.BasicGraphicsUtils; - -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Configurable; -import org.contikios.contiki.collect.Link; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public class MapPanel extends JPanel implements Configurable, Visualizer, ActionListener, MouseListener, MouseMotionListener { - - private static final long serialVersionUID = -8256619482599309425L; - - private static final Logger log = - Logger.getLogger(MapPanel.class.getName()); - - private static final boolean VISUAL_DRAG = true; - - private static final Color LINK_COLOR = new Color(0x40, 0x40, 0xf0, 0xff); - - private static final int delta = 7; - - private final CollectServer server; - private final String category; - private final boolean isMap; - private String title; - - private Timer timer; - - private JPopupMenu popupMenu; - private JCheckBoxMenuItem layoutItem; - private JCheckBoxMenuItem lockedItem; - private JMenuItem shakeItem; -// private JCheckBoxMenuItem dragItem; - private JCheckBoxMenuItem backgroundItem; - private JCheckBoxMenuItem showNetworkItem; - private JCheckBoxMenuItem configItem; - private JMenuItem resetNetworkItem; - private MapNode popupNode; - - private Hashtable<String,MapNode> nodeTable = new Hashtable<String,MapNode>(); - private MapNode[] nodeList = new MapNode[0]; - private boolean updateNodeList; - - private MapNode selectedNode; - private ArrayList<MapNode> selectedMapNodes = new ArrayList<MapNode>(); - private Node[] selectedNodes; - private MapNode draggedNode; - private long draggedTime; - - private ImageIcon mapImage; - private String mapName; - private boolean showBackground; - - private int layoutRepel = 100; - private int layoutAttract = 50; - private int layoutGravity = 1; - - private double etxFactor = 1.0; - - private boolean isLayoutActive = true; - private boolean hideNetwork = false; - - protected JPanel configPanel; - - public MapPanel(CollectServer server, String title, String category, boolean isMap) { - super(null); - this.server = server; - this.title = title; - this.category = category; - this.isMap = isMap; - setPreferredSize(new Dimension(300, 200)); - - popupMenu = new JPopupMenu(getTitle()); - if (!isMap) { - layoutItem = createCheckBoxMenuItem(popupMenu, "Update Layout", isLayoutActive); - popupMenu.add(layoutItem); - - lockedItem = createCheckBoxMenuItem(popupMenu, "Fixed Node Position", false); - shakeItem = createMenuItem(popupMenu, "Shake Nodes"); - popupMenu.addSeparator(); - } - - showNetworkItem = createCheckBoxMenuItem(popupMenu, "Show Network Info", true); - resetNetworkItem = createMenuItem(popupMenu, "Reset Network"); - popupMenu.addSeparator(); - if (isMap) { - backgroundItem = createCheckBoxMenuItem(popupMenu, "Show Background", false); - backgroundItem.setEnabled(false); - } else { - configItem = createCheckBoxMenuItem(popupMenu, "Show Layout Settings", false); - } - -// popupMenu.addSeparator(); -// dragItem = new JCheckBoxMenuItem("Visible Drag", true); -// popupMenu.add(dragItem); - - setBackground(Color.white); - addMouseListener(this); - addMouseMotionListener(this); - - if (!isMap) { - timer = new Timer(100, this); - - configPanel = new JPanel(new GridLayout(0, 1)); - configPanel.setBorder(LineBorder.createBlackLineBorder()); - - JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 1000, 1000 - layoutAttract); - slider.setBorder(new TitledBorder("Attract Factor: " + (1000 - layoutAttract))); - slider.addChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { - JSlider slider = (JSlider)e.getSource(); - layoutAttract = 1000 - slider.getValue(); - ((TitledBorder)slider.getBorder()).setTitle("Attract Factor: " + slider.getValue()); - } - }); - configPanel.add(slider); - - slider = new JSlider(JSlider.HORIZONTAL, 0, 1000, layoutRepel); - slider.setBorder(new TitledBorder("Repel Range: " + layoutRepel)); - slider.addChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { - JSlider slider = (JSlider)e.getSource(); - layoutRepel = slider.getValue(); - ((TitledBorder)slider.getBorder()).setTitle("Repel Range: " + layoutRepel); - } - }); - configPanel.add(slider); - - slider = new JSlider(JSlider.HORIZONTAL, 0, 100, layoutGravity); - slider.setBorder(new TitledBorder("Gravity: " + layoutGravity)); - slider.addChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { - JSlider slider = (JSlider)e.getSource(); - layoutGravity = slider.getValue(); - ((TitledBorder)slider.getBorder()).setTitle("Gravity: " + layoutGravity); - } - }); - configPanel.add(slider); - - final JFormattedTextField etxField = new JFormattedTextField(new Double(etxFactor)); - etxField.setBorder(BorderFactory.createTitledBorder("ETX factor")); - etxField.setColumns(5); - etxField.addPropertyChangeListener("value", new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent evt) { - etxFactor = ((Number)etxField.getValue()).doubleValue(); - repaint(); - } - }); - configPanel.add(etxField); - - configPanel.setVisible(false); - add(configPanel); - - addComponentListener(new ComponentAdapter() { - public void componentResized(ComponentEvent ev) { - if (configPanel.isVisible()) { - updateConfigLayout(); - } - } - }); - } - } - - public String getMapBackground() { - return isMap ? mapName : null; - } - - public boolean setMapBackground(String image) { - if (!isMap) { - return false; - } - if (image == null) { - mapImage = null; - mapName = null; - backgroundItem.setEnabled(false); - backgroundItem.setSelected(false); - showBackground = false; - repaint(); - return true; - } - - ImageIcon ii = new ImageIcon(image); - if (ii.getIconWidth() <= 0 || ii.getIconHeight() <= 0) { - log.warning("could not find image '" + image + '\''); - return false; - } - mapImage = ii; - mapName = image; - setPreferredSize(new Dimension(ii.getIconWidth(), ii.getIconHeight())); - showBackground = true; - backgroundItem.setEnabled(true); - backgroundItem.setSelected(true); - repaint(); - return true; - } - - private JCheckBoxMenuItem createCheckBoxMenuItem(JPopupMenu menu, String title, boolean isSelected) { - JCheckBoxMenuItem item = new JCheckBoxMenuItem(title, isSelected); - item.addActionListener(this); - menu.add(item); - return item; - } - - private JMenuItem createMenuItem(JPopupMenu menu, String title) { - JMenuItem item = new JMenuItem(title); - item.addActionListener(this); - menu.add(item); - return item; - } - - public void setVisible(boolean visible) { - if (visible) { - clear(); - if (timer != null) { - timer.start(); - } - } else { - if (timer != null) { - timer.stop(); - } - } - super.setVisible(visible); - } - - public void clear() { - setCursor(Cursor.getDefaultCursor()); - draggedNode = null; - updateSelected(); - } - - - // ------------------------------------------------------------------- - // Node handling - // ------------------------------------------------------------------- - - public Node getNode(String id) { - MapNode node = nodeTable.get(id); - return node != null ? node.node : null; - } - - public MapNode getMapNode(String id) { - return nodeTable.get(id); - } - - private MapNode addMapNode(Node nd) { - String id = nd.getID(); - MapNode node = nodeTable.get(id); - if (node == null) { - node = new MapNode(this, nd); - node.y = 10 + (int) (Math.random() * (Math.max(100, getHeight()) - 20)); - node.x = 10 + (int) (Math.random() * (Math.max(100, getWidth()) - 30)); - - String location = server.getConfig(isMap ? id : ("collect.map." + id)); - if (location != null) { - try { - String[] pos = location.split(","); - node.x = Integer.parseInt(pos[0].trim()); - node.y = Integer.parseInt(pos[1].trim()); - node.hasFixedLocation = !isMap; - } catch (Exception e) { - System.err.println("could not parse node location: " + location); - e.printStackTrace(); - } - } - - nodeTable.put(id, node); - updateNodeList = true; - } - return node; - } - - private MapNode[] getNodeList() { - if (updateNodeList) { - synchronized (nodeTable) { - updateNodeList = false; - nodeList = nodeTable.values().toArray(new MapNode[nodeTable.size()]); - } - } - return nodeList; - } - - - // ------------------------------------------------------------------- - // Visualizer - // ------------------------------------------------------------------- - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return title; - } - - @Override - public Component getPanel() { - return this; - } - - @Override - public void nodesSelected(Node[] nodes) { - if (selectedNodes != nodes) { - selectedNodes = nodes; - if (isVisible()) { - updateSelected(); - } - } - } - - private void updateSelected() { - if (selectedMapNodes.size() > 0) { - for(MapNode node : selectedMapNodes) { - node.isSelected = false; - } - selectedMapNodes.clear(); - } - - if (selectedNodes == null || selectedNodes.length == 0) { - selectedNode = null; - } else { - for (Node node : selectedNodes) { - MapNode mapNode = addMapNode(node); - selectedMapNodes.add(mapNode); - mapNode.isSelected = true; - } - selectedNode = selectedMapNodes.get(0); - } - - repaint(); - } - - @Override - public void nodeAdded(Node nd) { - addMapNode(nd); - if (isVisible()) { - repaint(); - } - } - - @Override - public void nodeDataReceived(SensorData sensorData) { - if (isVisible()) { - repaint(); - } - } - - @Override - public void clearNodeData() { - nodeTable.clear(); - updateNodeList = true; - nodesSelected(null); - if (isVisible()) { - repaint(); - } - } - - - // ------------------------------------------------------------------- - // Graphics - // ------------------------------------------------------------------- - - @Override - protected void paintComponent(Graphics g) { - Graphics2D g2d = (Graphics2D) g; - FontMetrics fm = g.getFontMetrics(); - int fnHeight = fm.getHeight(); - int fnDescent = fm.getDescent(); - int width = getWidth(); - int height = getHeight(); - - g.setColor(getBackground()); - g.fillRect(0, 0, width, height); - if (showBackground && isMap) { - mapImage.paintIcon(this, g, 0, 0); - } - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - - // Display legend - if (!hideNetwork) { - int legendWidth = fm.stringWidth("ETX"); - g.setColor(Color.black); - g.drawString("ETX", width - legendWidth - 10, 10 + fnHeight - fnDescent); - g.drawRect(width - legendWidth - 30, 8, legendWidth + 24, fnHeight + 4); - g.setColor(LINK_COLOR); - g2d.drawLine(width - legendWidth - 25, 10 + fnHeight / 2, - width - legendWidth - 15, 10 + fnHeight / 2); - } - - MapNode[] nodes = getNodeList(); - if (!isMap || !hideNetwork) { - g.setColor(LINK_COLOR); - for (MapNode n : nodes) { - for (int j = 0, mu = n.node.getLinkCount(); j < mu; j++) { - Link link = n.node.getLink(j); - MapNode linkNode = addMapNode(link.node); - int x2 = linkNode.x; - int y2 = linkNode.y; - g2d.drawLine(n.x, n.y, x2, y2); - drawArrow(g, n.x, n.y, x2, y2, 3); - if (!hideNetwork) { - int xn1, xn2, yn1, yn2; - if (n.x <= x2) { - xn1 = n.x; xn2 = x2; - yn1 = n.y; yn2 = y2; - } else { - xn1 = x2; xn2 = n.x; - yn1 = y2; yn2 = n.y; - } - int dx = xn1 + (xn2 - xn1) / 2 + 4; - int dy = yn1 + (yn2 - yn1) / 2 - fnDescent; - if (yn2 < yn1) { - dy += fnHeight - fnDescent; - } - g.drawString( - Double.toString(((int) (link.getETX() * etxFactor * 100 + 0.5)) / 100.0), - dx, dy); - } - } - } - } - - for (MapNode n : nodes) { - n.paint(g, n.x, n.y); - - g.setColor(Color.black); - if (n.isSelected) { - BasicGraphicsUtils.drawDashedRect(g, n.x - delta, n.y - delta, - 2 * delta, 2 * delta); - } - if (selectedNode != null && selectedNode.message != null) { - g.drawString(selectedNode.message, 10, 10); - } - } - } - - private Polygon arrowPoly = new Polygon(); - private void drawArrow(Graphics g, int xSource, int ySource, int xDest, int yDest, int delta) { - double dx = xSource - xDest; - double dy = ySource - yDest; - double dir = Math.atan2(dx, dy); - double len = Math.sqrt(dx * dx + dy * dy); - dx /= len; - dy /= len; - len -= delta; - xDest = xSource - (int) (dx * len); - yDest = ySource - (int) (dy * len); - g.drawLine(xDest, yDest, xSource, ySource); - - final int size = 8; - arrowPoly.reset(); - arrowPoly.addPoint(xDest, yDest); - arrowPoly.addPoint(xDest + xCor(size, dir + 0.5), yDest + yCor(size, dir + 0.5)); - arrowPoly.addPoint(xDest + xCor(size, dir - 0.5), yDest + yCor(size, dir - 0.5)); - arrowPoly.addPoint(xDest, yDest); - g.fillPolygon(arrowPoly); - } - - private int yCor(int len, double dir) { - return (int)(0.5 + len * Math.cos(dir)); - } - - private int xCor(int len, double dir) { - return (int)(0.5 + len * Math.sin(dir)); - } - - - // ------------------------------------------------------------------- - // ActionListener - // ------------------------------------------------------------------- - - public void actionPerformed(ActionEvent e) { - Object source = e.getSource(); - if (!isMap && source == timer) { - if (isLayoutActive) { - updateNodeLayout(); - repaint(); - } - - } else if (!isMap && source == lockedItem) { - if (popupNode != null) { - boolean wasFixed = popupNode.hasFixedLocation; - popupNode.hasFixedLocation = lockedItem.isSelected(); - if (wasFixed && !popupNode.hasFixedLocation) { - server.removeConfig("collect.map." + popupNode.node.getID()); - } else if (!wasFixed && popupNode.hasFixedLocation) { - server.setConfig("collect.map." + popupNode.node.getID(), - "" + popupNode.x + ',' + popupNode.y); - } - repaint(); - } - - } else if (!isMap && source == layoutItem) { - isLayoutActive = layoutItem.isSelected(); - - } else if (!isMap && source == shakeItem) { - for(MapNode n : getNodeList()) { - if (!n.hasFixedLocation) { - n.x += Math.random() * 100 - 50; - n.y += Math.random() * 100 - 50; - } - } - - } else if (!isMap && source == configItem) { - if (configItem.isSelected()) { - configPanel.setSize(getPreferredSize()); - configPanel.validate(); - updateConfigLayout(); - configPanel.setVisible(true); - } else { - configPanel.setVisible(false); - } - repaint(); - - } else if (source == showNetworkItem) { - hideNetwork = !showNetworkItem.isSelected(); - repaint(); - - } else if (source == resetNetworkItem) { - for(MapNode n : getNodeList()) { - n.node.clearLinks(); - } - repaint(); - } else if (isMap && source == backgroundItem) { - showBackground = mapImage != null && backgroundItem.isSelected(); - repaint(); - } - } - - private void updateNodeLayout() { - MapNode[] nodes = getNodeList(); - for (MapNode n : nodes) { - - // Attract connected nodes - for(int i = 0, jn = n.node.getLinkCount(); i < jn; i++) { - Link link = n.node.getLink(i); - MapNode n2 = addMapNode(link.node); - double vx = n2.x - n.x; - double vy = n2.y - n.y; - double dist = Math.sqrt(vx * vx + vy * vy); - dist = dist == 0 ? 0.00001 : dist; - double etx = link.getETX() * etxFactor; - if (etx > 5) etx = 5; - double factor = (etx * layoutAttract - dist) / (dist * 3); - double dx = factor * vx; - double dy = factor * vy; - - n2.dx += dx; - n2.dy += dy; - n.dx -= dx; - n.dy -= dy; - } - - // Repel nodes that are too close - double dx = 0, dy = 0; - for (MapNode n2 : nodes) { - if (n == n2) { - continue; - } - double vx = n.x - n2.x; - double vy = n.y - n2.y; - double dist = vx * vx + vy * vy; - if (dist == 0) { - dx += Math.random() * 5; - dy += Math.random() * 5; - } else if (dist < layoutRepel * layoutRepel) { - dx += vx / dist; - dy += vy / dist; - } - } - double dist = dx * dx + dy * dy; - if (dist > 0) { - dist = Math.sqrt(dist) / 2; - n.dx += dx / dist; - n.dy += dy / dist; - } - - n.dy += layoutGravity; - } - - // Update the node positions - int width = getWidth(); - int height = getHeight(); - for(MapNode n : nodes) { - if (!n.hasFixedLocation && n != draggedNode) { - n.x += Math.max(-5, Math.min(5, n.dx)); - n.y += Math.max(-5, Math.min(5, n.dy)); - if (n.x < 0) { - n.x = 0; - } else if (n.x > width) { - n.x = width; - } - if (n.y < 0) { - n.y = 0; - } else if (n.y > height) { - n.y = height; - } - } - n.dx /= 2; - n.dy /= 2; - } - } - - private void updateConfigLayout() { - configPanel.setLocation(getWidth() - configPanel.getWidth() - 10, - getHeight() - configPanel.getHeight() - 10); - } - - - // ------------------------------------------------------------------- - // Mouselistener - // ------------------------------------------------------------------- - - private MapNode getNodeAt(int mx, int my) { - for(MapNode n : getNodeList()) { - if (mx >= (n.x - delta) - && mx <= (n.x + delta) - && my >= (n.y - delta) - && my <= (n.y + delta)) { - return n; - } - } - return null; - } - - public void mouseClicked(MouseEvent e) { - int mx = e.getX(); - int my = e.getY(); - if (e.getButton() == MouseEvent.BUTTON1) { - MapNode node = getNodeAt(mx, my); - if (node != selectedNode) { - server.selectNodes(node == null ? null : new Node[] { node.node }); - } - } - showPopup(e); - } - - public void mousePressed(MouseEvent e) { - if (e.getButton() == MouseEvent.BUTTON1) { - MapNode aNode = getNodeAt(e.getX(), e.getY()); - if (aNode != selectedNode) { - server.selectNodes(aNode != null ? new Node[] { aNode.node } : null); - } - draggedNode = aNode; - draggedTime = System.currentTimeMillis(); - - } else if (selectedNode != null) { - if (draggedTime < 0) { - setCursor(Cursor.getDefaultCursor()); - draggedTime = 0; - } - selectedNode = draggedNode = null; - server.selectNodes(null); - } - showPopup(e); - } - - public void mouseReleased(MouseEvent e) { - if (draggedNode != null && e.getButton() == MouseEvent.BUTTON1) { - if ((draggedTime > 0) && - (System.currentTimeMillis() - draggedTime) < 300) { - // Do not drag if mouse is only moved during click - - } else { - draggedNode.x = e.getX(); - draggedNode.y = e.getY(); - setCursor(Cursor.getDefaultCursor()); - if (!isMap && draggedNode.hasFixedLocation) { - /* Update fixed location */ - server.setConfig("collect.map." + draggedNode.node.getID(), - "" + draggedNode.x + ',' + draggedNode.y); - } - draggedTime = 0; - draggedNode = null; - repaint(); - } - } - - showPopup(e); - } - - private void showPopup(MouseEvent e) { - if (e.isPopupTrigger() - && (e.getModifiers() & (MouseEvent.SHIFT_MASK|MouseEvent.CTRL_MASK)) == 0) { - popupNode = getNodeAt(e.getX(), e.getY()); - if (!isMap) { - lockedItem.setEnabled(popupNode != null); - lockedItem.setSelected(popupNode != null ? popupNode.hasFixedLocation : false); - } - popupMenu.show(this, e.getX(), e.getY()); - } - } - - public void mouseEntered(MouseEvent e) { - } - - public void mouseExited(MouseEvent e) { - } - - - // ------------------------------------------------------------------- - // MouseMotion - // ------------------------------------------------------------------- - - public void mouseDragged(MouseEvent e) { - if (draggedNode == null) { - // Do nothing - - } else if (draggedTime > 0) { - if ((System.currentTimeMillis() - draggedTime) > 300) { - // No mouse click, time to drag the node - draggedTime = -1; - setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); - } - - } else if (VISUAL_DRAG /* && dragItem.isSelected() */) { - draggedNode.x = e.getX(); - draggedNode.y = e.getY(); - repaint(); - } - } - - public void mouseMoved(MouseEvent e) { - } - - - // ------------------------------------------------------------------- - // MapNode - // ------------------------------------------------------------------- - - private static class MapNode { - - public final Node node; - public int x; - public int y; - public double dx; - public double dy; - public boolean hasFixedLocation; - public boolean isSelected; - public String message; - - MapNode(MapPanel panel, Node node) { - this.node = node; - } - - public void paint(Graphics g, int x, int y) { - final int od = 3; - g.setColor(Color.black); - g.drawString(node.getID(), x + od * 2 + 3, y + 4); - if (hasFixedLocation) { - g.setColor(Color.red); - } - g.fillOval(x - od, y - od, od * 2 + 1, od * 2 + 1); - } - - } // end of inner class MapNode - - - @Override - public void updateConfig(Properties config) { - if (isMap) { - for (MapNode n : getNodeList()) { - config.put(n.node.getID(), "" + n.x + ',' + n.y); - } - } - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeControl.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeControl.java deleted file mode 100644 index 6b0cffbc88b0f23c44794f5c37c9b011e9422273..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeControl.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * NodeControl - * - * Authors : Niclas Finne - * Created : 27 sep 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.FlowLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JFormattedTextField; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSeparator; -import javax.swing.JTextPane; -import javax.swing.border.LineBorder; - -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public class NodeControl implements Visualizer { - - private final static String SET_TIME_COMMAND = "time %TIME% | null"; - - private final CollectServer server; - private final String category; - private final JPanel panel; - private final JLabel statusLabel; - private final JSeparator statusSeparator; - - public NodeControl(CollectServer server, String category) { - this.server = server; - this.category = category; - this.panel = new JPanel(new BorderLayout()); - - final JFormattedTextField intervalField = new JFormattedTextField(new Integer(60)); - final JFormattedTextField randomField = new JFormattedTextField(new Integer(60)); - final JFormattedTextField reportsField = new JFormattedTextField(new Integer(0)); - final JFormattedTextField rexmitsField = new JFormattedTextField(new Integer(31)); - statusLabel = new JLabel("", JLabel.CENTER); - statusLabel.setOpaque(true); - statusLabel.setBackground(Color.white); - statusLabel.setBorder(LineBorder.createBlackLineBorder()); - statusLabel.setVisible(false); - statusSeparator = new JSeparator(); - statusSeparator.setVisible(false); - - JButton stopButton = createCommandButton("Send stop to nodes", "netcmd killall"); - - JButton sendButton = new JButton("Send command to nodes"); - sendButton.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - int interval = (Integer)intervalField.getValue(); - int random = (Integer)randomField.getValue(); - int reports = (Integer)reportsField.getValue(); - int rexmits = (Integer)rexmitsField.getValue(); - - sendCommand("netcmd { repeat " + reports + " " + interval - + " { randwait " + random + " collect-view-data | send " + rexmits + " } }"); - } - - }); - - JButton collectButton = createCommandButton("Start Collect", - "~K", "killall", - "mac 0", SET_TIME_COMMAND, - "collect | timestamp | binprint &"); - JButton stopCollectButton = createCommandButton("Stop Collect", "~K", "killall"); - - JPanel controlPanel = new JPanel(new GridBagLayout()); - - GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 0.5; - c.insets.left = c.insets.right = c.insets.bottom = 3; - c.anchor = GridBagConstraints.WEST; - c.gridy = 0; - - c.gridwidth = 3; - controlPanel.add(statusLabel, c); - c.gridy++; - controlPanel.add(statusSeparator, c); - c.insets.top = 10; - - c.gridy++; - c.gridwidth = 1; - controlPanel.add(new JLabel("Program Connected Nodes", JLabel.RIGHT), c); - c.gridwidth = 3; - c.fill = GridBagConstraints.NONE; - controlPanel.add(new JButton(server.getMoteProgramAction()), c); - c.fill = GridBagConstraints.HORIZONTAL; - - c.gridy++; - c.gridwidth = 1; - controlPanel.add(new JLabel("Serial Connection", JLabel.RIGHT), c); - c.gridwidth = 3; - c.fill = GridBagConstraints.NONE; - controlPanel.add(new JButton(server.getConnectSerialAction()), c); - c.fill = GridBagConstraints.HORIZONTAL; - - c.gridy++; - controlPanel.add(new JSeparator(), c); - - c.gridy++; - c.gridwidth = 1; - controlPanel.add(new JLabel("Base Station Control", JLabel.RIGHT), c); - c.gridwidth = 2; - JPanel basePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 5)); - basePanel.add(collectButton); - basePanel.add(stopCollectButton); - c.insets.left -= 5; - controlPanel.add(basePanel, c); - c.insets.left += 5; - - c.gridy++; - c.gridwidth = 3; - controlPanel.add(new JSeparator(), c); - - c.gridy++; - JLabel label = new JLabel("Collect Settings", JLabel.CENTER); - controlPanel.add(label, c); - c.gridwidth = 1; - - c.gridy++; - controlPanel.add(label = new JLabel("Report interval", JLabel.RIGHT), c); - label.setLabelFor(intervalField); - controlPanel.add(intervalField, c); - controlPanel.add(new JLabel("seconds"), c); - - c.insets.top = 3; - c.gridy++; - controlPanel.add(label = new JLabel("Report randomness", JLabel.RIGHT), c); - label.setLabelFor(randomField); - controlPanel.add(randomField, c); - controlPanel.add(new JLabel("seconds"), c); - - c.gridy++; - controlPanel.add(label = new JLabel("Hop-by-hop retransmissions", JLabel.RIGHT), c); - label.setLabelFor(rexmitsField); - controlPanel.add(rexmitsField, c); - controlPanel.add(new JLabel("retransmissions (0 - 31)"), c); - - c.gridy++; - controlPanel.add(new JLabel("Number of reports", JLabel.RIGHT), c); - label.setLabelFor(reportsField); - controlPanel.add(reportsField, c); - controlPanel.add(new JLabel("(0 = report forever)"), c); - - c.gridy++; - c.gridwidth = 3; - c.insets.bottom = 10; - JPanel nodePanel = new JPanel(); - nodePanel.add(sendButton); - nodePanel.add(stopButton); - controlPanel.add(nodePanel, c); - - c.gridy++; - controlPanel.add(new JSeparator(), c); - panel.add(controlPanel, BorderLayout.NORTH); - - JTextPane helpPane = new JTextPane(); - helpPane.setContentType("text/html"); - helpPane.setEditable(false); - helpPane.setText("<html>" + - "<h3>Quick Startup Instructions</h3>" + - "<lu>" + - "<li> Connect nodes to USB. Press the <strong>Program Nodes...</strong> button." + - "<li> Disconnect all except one node. " + - "Press the <strong>Connect to Serial</strong> button." + - "<li> Press the <strong>Start Collect</strong> button." + - "<li> Press the <strong>Send command to nodes</strong> button." + - "</lu>" + - "</html>"); - helpPane.setBackground(panel.getBackground()); - JScrollPane helpScroll = new JScrollPane(helpPane, - JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, - JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - helpScroll.setBorder(BorderFactory.createEmptyBorder(3, 10, 10, 10)); - panel.add(helpScroll, BorderLayout.CENTER); - } - - private JButton createCommandButton(String name, final String... command) { - JButton button = new JButton(name); - button.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - try { - // TODO Should use separate thread to send commands - panel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - for(int i = 0, n = command.length; i < n; i++) { - if (i > 0) { - try { - // Do not send multiple commands too fast - Thread.sleep(1000); - } catch (InterruptedException e1) { - } - } - String cmd = command[i]; - if (cmd == SET_TIME_COMMAND) { - cmd = "time " + (System.currentTimeMillis() / 1000) + " | null"; - } - if (!sendCommand(cmd)) { - break; - } - } - } finally { - panel.setCursor(Cursor.getDefaultCursor()); - } - } - - }); - return button; - } - - protected boolean sendCommand(String command) { - if (server.sendToNode(command)) { - setStatus("Sent command '" + command + "'", false); - return true; - } - setStatus("Failed to send command. No serial connection.", true); - return false; - } - - private void setStatus(String text, boolean isWarning) { - statusLabel.setForeground(isWarning ? Color.red : Color.black); - statusLabel.setText(text); - statusLabel.setVisible(true); - statusSeparator.setVisible(true); - } - - public String getCategory() { - return category; - } - - public String getTitle() { - return "Node Control"; - } - - public Component getPanel() { - return panel; - } - - public void nodesSelected(Node[] node) { - } - - public void nodeAdded(Node node) { - } - - public void nodeDataReceived(SensorData sensorData) { - } - - public void clearNodeData() { - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeInfoPanel.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeInfoPanel.java deleted file mode 100644 index dfda529934c945b36f7987b522c4f5f15c4e2e9e..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeInfoPanel.java +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * NodeInfoPanel - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 6 sep 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.Comparator; -import java.util.Properties; - -import javax.swing.AbstractAction; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.SwingUtilities; -import javax.swing.table.AbstractTableModel; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.JTableHeader; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumn; -import javax.swing.table.TableRowSorter; - -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Configurable; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.SensorInfo; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public class NodeInfoPanel extends JPanel implements Visualizer, Configurable { - - private static final long serialVersionUID = -1060893468047793431L; - - private static Comparator<Number> NUMBER_COMPARATOR = new Comparator<Number>() { - - public int compare(Number o1, Number o2) { - double v1 = o1.doubleValue(); - double v2 = o2.doubleValue(); - return (v1 < v2 ? -1 : (v1 == v2 ? 0 : 1)); - } - - }; - - private final CollectServer server; - private final String category; - private final JTable table; - private final NodeModel nodeModel; - - @SuppressWarnings("serial") - public NodeInfoPanel(CollectServer server, String category) { - super(new BorderLayout()); - this.server = server; - this.category = category; - - TableData[] columns = new TableData[] { - new TableData("Node", Node.class) { - public Object getValue(Node node) { - return node; - } - }, - new TableData("Received", "Packets Received", Number.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getPacketCount(); - } - }, - new TableData("Dups", "Duplicate Packets Received", Number.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getDuplicateCount(); - } - }, - new TableData("Lost", "Estimated Lost Packets", Number.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getEstimatedLostCount(); - } - }, - new TableData("Hops", "Average Hops to Sink", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getAverageValue(SensorData.HOPS); - } - }, - new TableData("Rtmetric", "Average Routing Metric", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getAverageRtmetric(); - } - }, - new TableData("ETX", "Average ETX to Next Hop", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getAverageBestNeighborETX(); - } - }, - new TableData("Churn", "Next Hop Change Count", Number.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getNextHopChangeCount(); - } - }, - new TableData("Beacon Interval", "Average Beacon Interval", Long.class) { - public Object getValue(Node node) { - return (long)(node.getSensorDataAggregator().getAverageValue(SensorData.BEACON_INTERVAL) * 1000); - } - }, - - new TableData("Reboots", "Estimated Node Restart Count", Number.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getEstimatedRestarts(); - } - }, - - // Power - new TableData("CPU Power", "Average CPU Power Consumption", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getCPUPower(); - } - }, - new TableData("LPM Power", "Average LPM Power Consumption", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getLPMPower(); - } - }, - new TableData("Listen Power", "Average Radio Listen Power Consumption", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getListenPower(); - } - }, - new TableData("Transmit Power", "Average Radio Transmit Power Consumption", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getTransmitPower(); - } - }, - new TableData("Power", "Average Power Consumption", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getAveragePower(); - } - }, - new TableData("On-time", "Power Measure Time", Long.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getPowerMeasureTime(); - } - }, - - new TableData("Listen Duty Cycle", "Average Radio Listen Duty Cycle (%)", Double.class) { - public Object getValue(Node node) { - return 100 * node.getSensorDataAggregator().getAverageDutyCycle(SensorInfo.TIME_LISTEN); - } - }, - new TableData("Transmit Duty Cycle", "Average Radio Transmit Duty Cycle (%)", Double.class) { - public Object getValue(Node node) { - return 100 * node.getSensorDataAggregator().getAverageDutyCycle(SensorInfo.TIME_TRANSMIT); - } - }, - - // Inter-packet times - new TableData("Avg Inter-packet Time", Long.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getAveragePeriod(); - } - }, - new TableData("Min Inter-packet Time", Long.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getShortestPeriod(); - } - }, - new TableData("Max Inter-packet Time", Long.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getLongestPeriod(); - } - } - }; - nodeModel = new NodeModel(columns); - table = new JTable(nodeModel) { - private static final long serialVersionUID = 1L; - private Font fontForAverage; - - protected JTableHeader createDefaultTableHeader() { - return new JTableHeader(columnModel) { - private static final long serialVersionUID = 1L; - - public String getToolTipText(MouseEvent e) { - int index = columnModel.getColumnIndexAtX(e.getX()); - int modelIndex = index < 0 ? index : columnModel.getColumn(index).getModelIndex(); - return modelIndex < 0 ? null : nodeModel.getColumnToolTip(modelIndex); - } - }; - } - - public Component prepareRenderer(TableCellRenderer renderer, int rowIndex, int vColIndex) { - Component c = super.prepareRenderer(renderer, rowIndex, vColIndex); - int row = convertRowIndexToModel(rowIndex); - if (row == nodeModel.getRowCount() - 1) { - if (fontForAverage == null) { - fontForAverage = c.getFont().deriveFont(Font.BOLD); - } - // Last line is average - c.setFont(fontForAverage); - } - return c; - } - - }; - - // Do not sort column when clicking between the columns (resizing) - TableRowSorter<NodeModel> sorter = new TableRowSorter<NodeModel>(nodeModel) { - public void toggleSortOrder(int column) { - if(table.getTableHeader().getCursor().getType() != Cursor.E_RESIZE_CURSOR) { - super.toggleSortOrder(column); - } - } - }; - for(int c = 0; c < columns.length; c++) { - if (columns[c].dataClass == Number.class) { - sorter.setComparator(c, NUMBER_COMPARATOR); - } - } - table.setRowSorter(sorter); - // Pack the column when double clicking between columns (resizing) - table.getTableHeader().addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if(e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e) && - table.getTableHeader().getCursor().getType() == Cursor.E_RESIZE_CURSOR) { - int index = table.getColumnModel().getColumnIndexAtX(e.getX() - 3); - if (index >= 0) { - packColumn(table, index); - } - } - } - }); - - // Add right aligned renderer for node name - DefaultTableCellRenderer renderer = new DefaultTableCellRenderer(); - renderer.setHorizontalAlignment(JLabel.RIGHT); - table.setDefaultRenderer(Node.class, renderer); - - // Add renderer for time - renderer = new DefaultTableCellRenderer() { - private static final long serialVersionUID = 1L; - - public void setValue(Object value) { - long time = (Long) value; - setText(time > 0 ? getTimeAsString(time) : null); - } - }; - renderer.setHorizontalAlignment(JLabel.RIGHT); - table.setDefaultRenderer(Long.class, renderer); - - // Add renderer for double - renderer = new DefaultTableCellRenderer() { - private static final long serialVersionUID = 1L; - - public void setValue(Object value) { - if (value == null) { - setText(null); - } else { - double v = ((Number) value).doubleValue() + 0.0005; - int dec = ((int)(v * 1000)) % 1000; - setText((long)v + "." + (dec > 99 ? "" : "0") + (dec > 9 ? "" : "0") + dec); - } - } - }; - renderer.setHorizontalAlignment(JLabel.RIGHT); - table.setDefaultRenderer(Double.class, renderer); - - // Add renderer for mixed integers and doubles - renderer = new DefaultTableCellRenderer() { - private static final long serialVersionUID = 1L; - - public void setValue(Object value) { - if (value == null) { - setText(null); - } else if (value instanceof Integer) { - setText(value.toString()); - } else { - double v = ((Number) value).doubleValue() + 0.0005; - int dec = ((int)(v * 1000)) % 1000; - setText((long)v + "." + (dec > 99 ? "" : "0") + (dec > 9 ? "" : "0") + dec); - } - } - }; - renderer.setHorizontalAlignment(JLabel.RIGHT); - table.setDefaultRenderer(Number.class, renderer); - - table.setFillsViewportHeight(true); - table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); - for (int i = 0, n = table.getColumnCount(); i < n; i++) { - packColumn(table, i); - } - - String savedColumnData = server.getConfig("collect.nodeinfo.table"); - if (savedColumnData != null) { - String[] columnList = savedColumnData.split("[ ,]"); - for(int i = 1; i < columns.length; i++) { - columns[i].setVisible(false); - } - for(int i = 0; i < columnList.length; i++) { - int c = Integer.parseInt(columnList[i]); - int index = table.convertColumnIndexToView(c); - if (index >= 0) { - table.getColumnModel().moveColumn(index, i); - } - columns[c].setVisible(true); - } - } - JPopupMenu popupMenu = new JPopupMenu(); - // The first column (the node name) should always be visible. - for(int i = 1; i < columns.length; i++) { - popupMenu.add(new JCheckBoxMenuItem(columns[i].init(table, i))); - } - table.setComponentPopupMenu(popupMenu); - add(new JScrollPane(table), BorderLayout.CENTER); - } - - public void updateConfig(Properties config) { - StringBuilder sb = new StringBuilder(); - for(int i = 0, n = table.getColumnCount(); i < n; i++) { - int index = table.convertColumnIndexToModel(i); - if (index >= 0) { - if (sb.length() > 0) { - sb.append(','); - } - sb.append(index); - } - } - config.setProperty("collect.nodeinfo.table", sb.toString()); - } - - @Override - public Component getPanel() { - return this; - } - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return "Node Info"; - } - - @Override - public void nodeAdded(Node node) { - nodeModel.setNodes(server.getNodes()); - } - - @Override - public void nodeDataReceived(SensorData sensorData) { - nodeModel.updateNode(sensorData.getNode()); - } - - @Override - public void clearNodeData() { - nodeModel.setNodes(null); - } - - @Override - public void nodesSelected(Node[] nodes) { - // Ignore - } - - @Override - public void setVisible(boolean visible) { - nodeModel.setNodes(visible ? server.getNodes() : null); - super.setVisible(visible); - } - - private String getTimeAsString(long time) { - StringBuilder sb = new StringBuilder(); - time /= 1000; - if (time > 24 * 60 * 60) { - long days = time / (24 * 60 * 60); - sb.append(days).append(days > 1 ? " days, " : " day, "); - time -= days * 24 * 60 * 60; - } - if (time > 60 * 60) { - long hours = time / (60 * 60); - sb.append(hours).append(hours > 1 ? " hours, " : " hour, "); - time -= hours * 60 * 60; - } - long sec = time % 60; - sb.append(time / 60).append(" min, "); - if (sec < 10) { - sb.append('0'); - } - sb.append(sec).append(" sec"); - return sb.toString(); - } - - private static void packColumn(JTable table, int columnIndex) { - TableColumn tableColumn = table.getColumnModel().getColumn(columnIndex); - Object value = tableColumn.getHeaderValue(); - TableCellRenderer columnRenderer = tableColumn.getHeaderRenderer(); - if (columnRenderer == null) { - columnRenderer = table.getTableHeader().getDefaultRenderer(); - } - Component c = columnRenderer.getTableCellRendererComponent(table, value, false, false, -1, columnIndex); - int width = c.getPreferredSize().width + 6; - int intercellSpacing = table.getIntercellSpacing().width; - for(int i = 0, n = table.getRowCount(); i < n; i++) { - TableCellRenderer cellRenderer = table.getCellRenderer(i, columnIndex); - value = table.getValueAt(i, columnIndex); - c = cellRenderer.getTableCellRendererComponent(table, value, false, false, i, columnIndex); - int w = c.getPreferredSize().width + intercellSpacing + 2; - if (w > width) { - width = w; - } - } - table.getTableHeader().setResizingColumn(tableColumn); - tableColumn.setWidth(width); - tableColumn.setPreferredWidth(width); - } - - private static class NodeModel extends AbstractTableModel { - - private static final long serialVersionUID = 1692207305977527004L; - - private final TableData[] columns; - private Node[] nodes; - - public NodeModel(TableData[] columns) { - this.columns = columns; - } - - public void recalculateAverage() { - for(TableData td : columns) { - td.clearAverageCache(); - } - int row = getRowCount() - 1; - fireTableRowsUpdated(row, row); - } - - public Object getValueAt(int row, int col) { - int count = nodes == null ? 0 : nodes.length; - if (row == count) { - return columns[col].getAverageValue(nodes); - } - return columns[col].getValue(nodes[row]); - } - - public Class<?> getColumnClass(int col) { - return columns[col].dataClass; - } - - public String getColumnName(int col) { - return columns[col].name; - } - - public String getColumnToolTip(int col) { - Object v = columns[col].getValue(TableData.SHORT_DESCRIPTION); - return v == null ? null : v.toString(); - } - - public int getColumnCount() { - return columns.length; - } - - public int getRowCount() { - return (nodes == null ? 0 : nodes.length) + 1; - } - - public void setNodes(Node[] nodes) { - if (this.nodes != null && this.nodes.length > 0) { - fireTableRowsDeleted(0, this.nodes.length - 1); - } - this.nodes = nodes; - if (this.nodes != null && this.nodes.length > 0) { - fireTableRowsInserted(0, this.nodes.length - 1); - } - recalculateAverage(); - } - - public void updateNode(Node node) { - if (this.nodes != null) { - for(int row = 0; row < this.nodes.length; row++) { - if (this.nodes[row] == node) { - fireTableRowsUpdated(row, row); - recalculateAverage(); - break; - } - } - } - } - - } - - public static abstract class TableData extends AbstractAction { - private static final long serialVersionUID = -3045755073722516926L; - - private final static Node AVERAGE_NODE = new Node("99999999.9", "Avg"); - - public final String name; - public final Class<?> dataClass; - - private JTable table; - private TableColumn tableColumn; - private int modelIndex = -1; - - private Object averageCache; - - protected TableData(String name, Class<?> dataClass) { - this(name, name, dataClass); - } - - protected TableData(String name, String description, Class<?> dataClass) { - super(name); - this.name = name; - this.dataClass = dataClass; - putValue(SHORT_DESCRIPTION, description); - setVisible(true); - } - - TableData init(JTable table, int modelIndex) { - this.table = table; - this.modelIndex = modelIndex; - if (!isVisible()) { - // The column should initially be hidden - setColumnVisible(false); - } - return this; - } - - public boolean isVisible() { - return Boolean.TRUE.equals(getValue(SELECTED_KEY)); - } - - public TableData setVisible(boolean isVisible) { - putValue(SELECTED_KEY, isVisible); - return this; - } - - public void actionPerformed(ActionEvent event) { - if (modelIndex >= 0) { - setColumnVisible(isVisible()); - } - } - - private void setColumnVisible(boolean isVisible) { - if (isVisible) { - if (tableColumn != null) { - int count = table.getColumnCount(); - table.addColumn(tableColumn); - tableColumn = null; - packColumn(table, count); - - int newIndex = 0; - for(int i = 0; i < modelIndex; i++) { - if (table.convertColumnIndexToView(i) >= 0) { - // The new column should be after this visible column - newIndex++; - } - } - if (newIndex < count) { - table.getColumnModel().moveColumn(count, newIndex); - } - } - } else { - int columnIndex = table.convertColumnIndexToView(modelIndex); - if (columnIndex >= 0 ) { - tableColumn = table.getColumnModel().getColumn(columnIndex); - table.removeColumn(tableColumn); - } - } - } - - public final Object getAverageValue(Node[] nodes) { - Object tmp = averageCache; - if (tmp != null) { - return tmp; - } - - if (dataClass == Long.class || dataClass == Double.class - || dataClass == Number.class) { - double average = 0.0; - if (nodes != null && nodes.length > 0) { - int count = 0; - for(Node node : nodes) { - if (node.getSensorDataAggregator().getDataCount() > 0) { - average += ((Number) getValue(node)).doubleValue(); - count++; - } - } - if (count > 0) { - average = average / count; - } - } - if (dataClass == Long.class) { - tmp = (long) (average + 0.5); - } else { - tmp = average; - } - } else if (dataClass == Node.class) { - tmp = AVERAGE_NODE; - } - averageCache = tmp; - return tmp; - } - - public final void clearAverageCache() { - averageCache = null; - } - - public abstract Object getValue(Node node); - - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/SerialConsole.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/SerialConsole.java deleted file mode 100644 index ef7b0c7e59fb5241b108b4d1876fc43ee98e1d74..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/SerialConsole.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * SerialConsole - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 4 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.JTextField; -import javax.swing.SwingUtilities; -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public class SerialConsole implements Visualizer { - - private final CollectServer server; - private final String category; - private JPanel panel; - private JTextArea logArea; - private JTextField commandField; - private String[] history = new String[50]; - private int historyPos = 0; - private int historyCount = 0; - - public SerialConsole(CollectServer server, String category) { - this.server = server; - this.category = category; - panel = new JPanel(new BorderLayout()); - logArea = new JTextArea(4, 30); - logArea.setEditable(false); - panel.add(new JScrollPane(logArea), BorderLayout.CENTER); - - JPopupMenu popupMenu = new JPopupMenu(); - JMenuItem clearItem = new JMenuItem("Clear"); - clearItem.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - logArea.setText(""); - } - - }); - popupMenu.add(clearItem); - logArea.setComponentPopupMenu(popupMenu); - - commandField = new JTextField(); - commandField.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - String command = trim(commandField.getText()); - if (command != null) { - try { - int previous = historyCount - 1; - if (previous < 0) previous += history.length; - if (!command.equals(history[previous])) { - history[historyCount] = command; - historyCount = (historyCount + 1) % history.length; - } - historyPos = historyCount; - if (SerialConsole.this.server.sendToNode(command)) { - commandField.setText(""); - } else { - addSerialData("*** failed to send command ***"); - } - } catch (Exception ex) { - System.err.println("could not send '" + command + "':"); - ex.printStackTrace(); - JOptionPane.showMessageDialog(panel, - "could not send '" + command + "':\n" - + ex, "ERROR", - JOptionPane.ERROR_MESSAGE); - } - } else { - commandField.getToolkit().beep(); - } - } - - }); - commandField.addKeyListener(new KeyAdapter() { - - @Override - public void keyPressed(KeyEvent e) { - switch (e.getKeyCode()) { - case KeyEvent.VK_UP: { - int nextPos = (historyPos + history.length - 1) % history.length; - if (nextPos == historyCount || history[nextPos] == null) { - commandField.getToolkit().beep(); - } else { - String cmd = trim(commandField.getText()); - if (cmd != null) { - history[historyPos] = cmd; - } - historyPos = nextPos; - commandField.setText(history[historyPos]); - } - break; - } - case KeyEvent.VK_DOWN: { - int nextPos = (historyPos + 1) % history.length; - if (nextPos == historyCount) { - historyPos = nextPos; - commandField.setText(""); - } else if (historyPos == historyCount || history[nextPos] == null) { - commandField.getToolkit().beep(); - } else { - String cmd = trim(commandField.getText()); - if (cmd != null) { - history[historyPos] = cmd; - } - historyPos = nextPos; - commandField.setText(history[historyPos]); - } - break; - } - } - } - - }); - panel.add(commandField, BorderLayout.SOUTH); - } - - @Override - public Component getPanel() { - return panel; - } - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return "Serial Console"; - } - - @Override - public void nodeAdded(Node node) { - // Ignore - } - - @Override - public void nodeDataReceived(SensorData sensorData) { - // Ignore - } - - @Override - public void clearNodeData() { - // Ignore - } - - @Override - public void nodesSelected(Node[] node) { - // Ignore - } - - public void addSerialData(final String text) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - String current = logArea.getText(); - int len = current.length(); - if (len > 4096) { - current = current.substring(len - 4096); - } - current = len > 0 ? (current + '\n' + text) : text; - logArea.setText(current); - logArea.setCaretPosition(current.length()); - } - }); - } - - private String trim(String text) { - return (text != null) && ((text = text.trim()).length() > 0) ? text : null; - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/TimeChartPanel.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/TimeChartPanel.java deleted file mode 100644 index 206e25b5c758664d68960dab243db85ebc98fcc6..0000000000000000000000000000000000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/TimeChartPanel.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * ----------------------------------------------------------------- - * - * TimeChartPanel - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Dimension; -import java.util.Date; -import javax.swing.JPanel; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; -import org.jfree.data.time.Second; -import org.jfree.data.time.TimeSeries; -import org.jfree.data.time.TimeSeriesCollection; -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public abstract class TimeChartPanel extends JPanel implements Visualizer { - - private static final long serialVersionUID = -607864439709540641L; - - protected final CollectServer server; - protected final String category; - protected final String title; - protected final TimeSeriesCollection timeSeries; - protected final JFreeChart chart; - protected final ChartPanel chartPanel; - - private Node[] selectedNodes; - - private double minValue; - private double maxValue; - private int rangeTick = 0; - private boolean hasGlobalRange; - private int maxItemCount; - - public TimeChartPanel(CollectServer server, String category, String title, - String chartTitle, String timeAxisLabel, String valueAxisLabel) { - super(new BorderLayout()); - this.server = server; - this.category = category; - this.title = title; - this.timeSeries = new TimeSeriesCollection(); - this.chart = ChartFactory.createTimeSeriesChart( - chartTitle, timeAxisLabel, valueAxisLabel, timeSeries, - true, true, false - ); - this.chartPanel = new ChartPanel(chart); - this.chartPanel.setPreferredSize(new Dimension(500, 270)); - setBaseShapeVisible(true); - setMaxItemCount(server.getDefaultMaxItemCount()); - add(chartPanel, BorderLayout.CENTER); - } - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return title; - } - - @Override - public Component getPanel() { - return this; - } - - @Override - public void nodeAdded(Node node) { - // Ignore - } - - @Override - public void nodesSelected(Node[] nodes) { - if (this.selectedNodes != nodes) { - this.selectedNodes = nodes; - if (isVisible()) { - updateCharts(); - } - } - } - - @Override - public void nodeDataReceived(SensorData data) { - if (hasGlobalRange) { - boolean update = false; - if (minValue > maxValue) { - update = true; - } else { - double value = getSensorDataValue(data); - if (value < minValue) { - minValue = value; - update = true; - } - if (value > maxValue) { - maxValue = value; - update = true; - } - } - if (update && isVisible()) { - updateGlobalRange(); - } - } - if (isVisible() && selectedNodes != null && selectedNodes.length == timeSeries.getSeriesCount()) { - Node node = data.getNode(); - for (int i = 0, n = selectedNodes.length; i < n; i++) { - if (node == selectedNodes[i]) { - TimeSeries series = timeSeries.getSeries(i); - int groupSize = getGroupSize(node); - if (groupSize > 1) { - series.clear(); - updateSeries(series, node, groupSize); - } else { - series.addOrUpdate(new Second(new Date(data.getNodeTime())), getSensorDataValue(data)); - } - chartPanel.repaint(); - break; - } - } - } - } - - @Override - public void clearNodeData() { - if (isVisible()) { - updateCharts(); - } - } - - private void updateCharts() { - timeSeries.removeAllSeries(); - if (this.selectedNodes != null) { - for(Node node: this.selectedNodes) { - TimeSeries series = new TimeSeries(node.getName(), Second.class); - // Reduce the number of items by grouping them and use the average for each group - int groupSize = getGroupSize(node); - if (groupSize > 1) { - updateSeries(series, node, groupSize); - } else { - for (int i = 0, n = node.getSensorDataCount(); i < n; i++) { - SensorData data = node.getSensorData(i); - series.addOrUpdate(new Second(new Date(data.getNodeTime())), getSensorDataValue(data)); - } - } - timeSeries.addSeries(series); - } - } - } - - protected int getGroupSize(Node node) { - if (maxItemCount > 0) { - int sensorDataCount = node.getSensorDataCount(); - if (sensorDataCount > maxItemCount) { - int groupSize = sensorDataCount / maxItemCount; - if (sensorDataCount / groupSize >= maxItemCount) { - groupSize++; - } - return groupSize; - } - } - return 1; - } - - protected void updateSeries(TimeSeries series, Node node, int groupSize) { - for (int i = 0, n = node.getSensorDataCount(); i < n; i += groupSize) { - double value = 0.0; - long time = 0L; - for (int j = 0; j < groupSize; j++) { - SensorData data = node.getSensorData(i); - value += getSensorDataValue(data); - time += data.getNodeTime() / 1000L; - } - series.addOrUpdate(new Second(new Date((time / groupSize) * 1000L)), value / groupSize); - } - } - - public boolean getBaseShapeVisible() { - return ((XYLineAndShapeRenderer)this.chart.getXYPlot().getRenderer()).getBaseShapesVisible(); - } - - public void setBaseShapeVisible(boolean visible) { - ((XYLineAndShapeRenderer)this.chart.getXYPlot().getRenderer()).setBaseShapesVisible(visible); - } - - public int getRangeTick() { - return rangeTick; - } - - public void setRangeTick(int rangeTick) { - this.rangeTick = rangeTick; - } - - public double getRangeMinimumSize() { - return chart.getXYPlot().getRangeAxis().getAutoRangeMinimumSize(); - } - - public void setRangeMinimumSize(double size) { - chart.getXYPlot().getRangeAxis().setAutoRangeMinimumSize(size); - } - - public boolean hasGlobalRange() { - return hasGlobalRange; - } - - public void setGlobalRange(boolean hasGlobalRange) { - if (this.hasGlobalRange != hasGlobalRange) { - this.hasGlobalRange = hasGlobalRange; - if (hasGlobalRange) { - minValue = Double.MAX_VALUE; - maxValue = Double.MIN_NORMAL; - if (isVisible()) { - updateGlobalRange(); - } - } else { - chart.getXYPlot().getRangeAxis().setAutoRange(true); - } - } - } - - private void updateGlobalRange() { - if (hasGlobalRange) { - if (minValue > maxValue) { - for (int i = 0, n = server.getSensorDataCount(); i < n; i++) { - double value = getSensorDataValue(server.getSensorData(i)); - if (value < minValue) minValue = value; - if (value > maxValue) maxValue = value; - } - } - if (minValue < maxValue) { - double minSize = getRangeMinimumSize(); - double min = minValue; - double max = maxValue; - if (max - min < minSize) { - double d = (minSize - (max - min)) / 2; - min -= d; - max += d; - } - if (rangeTick > 0) { - min = ((int) (min - rangeTick / 2) / rangeTick) * rangeTick; -// max = ((int) (max + rangeTick / 2) / rangeTick) * rangeTick; - } - chart.getXYPlot().getRangeAxis().setRange(min, max); - } - } - } - - /** - * Returns the maximal number of chart items to display for each node. - * - * @return the maximal number of chart items to display for each node or <code>0</code> - * for unlimited number of chart items. - */ - public int getMaxItemCount() { - return maxItemCount; - } - - /** - * Sets the maximal number of chart items to display for each node. Items will be - * grouped and replaced by the average value when needed. - * - * @param maxItemCount - the maximal number of chart items to display for each node or - * <code>0</code> for unlimited number (default) - */ - public void setMaxItemCount(int maxItemCount) { - this.maxItemCount = maxItemCount; - if (isVisible()) { - updateCharts(); - } - } - - public void setVisible(boolean visible) { - if (visible) { - updateGlobalRange(); - updateCharts(); - } else { - timeSeries.removeAllSeries(); - } - super.setVisible(visible); - } - - protected abstract double getSensorDataValue(SensorData data); - -} diff --git a/tools/cooja b/tools/cooja index 8799528a5851f7e5af394f3f38e4a82b378e67af..22b1262d9e668d9cf6c8eaf70715f1bcd5728642 160000 --- a/tools/cooja +++ b/tools/cooja @@ -1 +1 @@ -Subproject commit 8799528a5851f7e5af394f3f38e4a82b378e67af +Subproject commit 22b1262d9e668d9cf6c8eaf70715f1bcd5728642 diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..d8e9c0a7989f080bce0319f869897ca133c65b20 --- /dev/null +++ b/tools/docker/Dockerfile @@ -0,0 +1,90 @@ +FROM 32bit/ubuntu:16.04 + +# Tools +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + build-essential doxygen git wget unzip python-serial \ + default-jdk ant srecord iputils-tracepath && \ + apt-get clean + +# Install ARM toolchain +RUN wget https://launchpad.net/gcc-arm-embedded/5.0/5-2015-q4-major/+download/gcc-arm-none-eabi-5_2-2015q4-20151219-linux.tar.bz2 && \ + tar xjf gcc-arm-none-eabi-5_2-2015q4-20151219-linux.tar.bz2 -C /tmp/ && \ + cp -f -r /tmp/gcc-arm-none-eabi-5_2-2015q4/* /usr/local/ && \ + rm -rf /tmp/gcc-arm-none-eabi-* gcc-arm-none-eabi-*-linux.tar.bz2 + +# Install msp430 toolchain +RUN wget http://simonduq.github.io/resources/mspgcc-4.7.2-compiled.tar.bz2 && \ + tar xjf mspgcc*.tar.bz2 -C /tmp/ && \ + cp -f -r /tmp/msp430/* /usr/local/ && \ + rm -rf /tmp/msp430 mspgcc*.tar.bz2 + +# Install NXP toolchain (partial, with binaries excluded. Download from nxp.com) +RUN wget http://simonduq.github.io/resources/ba-elf-gcc-4.7.4-part1.tar.bz2 && \ + wget http://simonduq.github.io/resources/ba-elf-gcc-4.7.4-part2.tar.bz2 && \ + wget http://simonduq.github.io/resources/jn516x-sdk-4163-1416.tar.bz2 && \ + mkdir /tmp/jn516x-sdk /tmp/ba-elf-gcc && \ + tar xjf jn516x-sdk-*.tar.bz2 -C /tmp/jn516x-sdk && \ + tar xjf ba-elf-gcc-*part1.tar.bz2 -C /tmp/ba-elf-gcc && \ + tar xjf ba-elf-gcc-*part2.tar.bz2 -C /tmp/ba-elf-gcc && \ + cp -f -r /tmp/jn516x-sdk /usr/ && \ + cp -f -r /tmp/ba-elf-gcc /usr/ && \ + rm -rf jn516x*.bz2 ba-elf-gcc*.bz2 /tmp/ba-elf-gcc* /tmp/jn516x-sdk* + +ENV PATH="/usr/ba-elf-gcc/bin:${PATH}" + +## Install nRF52 SDK +RUN wget https://developer.nordicsemi.com/nRF5_IoT_SDK/nRF5_IoT_SDK_v0.9.x/nrf5_iot_sdk_3288530.zip && \ + mkdir /usr/nrf52-sdk && \ + unzip nrf5_iot_sdk_3288530.zip -d /usr/nrf52-sdk && \ + rm nrf5_iot_sdk_3288530.zip + +ENV NRF52_SDK_ROOT /usr/nrf52-sdk + +# Create user, enable X forwarding, add to group dialout +# -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix +RUN export uid=1000 gid=1000 && \ + mkdir -p /home/user && \ + echo "user:x:${uid}:${gid}:user,,,:/home/user:/bin/bash" >> /etc/passwd && \ + echo "user:x:${uid}:" >> /etc/group && \ + echo "user ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers && \ + chmod 0440 /etc/sudoers && \ + chown ${uid}:${gid} -R /home/user && \ + usermod -aG dialout user + +# Set user for what comes next +USER user + +# Environment variables +ENV JAVA_HOME /usr/lib/jvm/default-java +ENV HOME /home/user +ENV CONTIKI_NG ${HOME}/contiki-ng +ENV COOJA ${CONTIKI_NG}/tools/cooja +ENV PATH="${HOME}:${PATH}" +WORKDIR ${HOME} + +# Create Cooja shortcut +RUN echo "#!/bin/bash\nant -Dbasedir=${COOJA} -f ${COOJA}/build.xml run" > ${HOME}/cooja && \ + chmod +x ${HOME}/cooja + +# Install coap-cli +RUN sudo apt-get install -y npm \ + && sudo apt-get clean \ + && sudo npm install coap-cli -g \ + && sudo ln -s /usr/bin/nodejs /usr/bin/node + +# Optional: download Contiki-NG and pre-compile Cooja. +# Else, use a Docker bind mount to share the repo with the host. +# Docker run option: +# -v <HOST_CONTIKI_NG_ABS_PATH>:/home/user/contiki-ng +RUN git clone --recursive https://github.com/contiki-ng/contiki-ng.git ${CONTIKI_NG} +RUN ant -q -f ${CONTIKI_NG}/tools/cooja/build.xml jar + +# Working directory +WORKDIR ${CONTIKI_NG} + +# Enable IPv6 -- must be done at runtime, not in Dockerfile +RUN echo "sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0 > /dev/null" >> /home/user/.profile + +# Start a bash +CMD bash --login diff --git a/tools/doxygen/Doxyfile b/tools/doxygen/Doxyfile index 8073a82392d4e06c0a522fdf598aab624865b55e..a7dc79fab359886576a5d88c2f5763053d5f9023 100644 --- a/tools/doxygen/Doxyfile +++ b/tools/doxygen/Doxyfile @@ -809,7 +809,8 @@ EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = */cpu/cc26xx-cc13xx/lib/* \ */cpu/cc26xx-cc13xx/rf-core/api/* \ - */platform/stm32nucleo-spirit1/stm32cube-lib/* + */platform/stm32nucleo-spirit1/stm32cube-lib/* \ + */os/net/security/tinydtls/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the @@ -1952,10 +1953,7 @@ INCLUDE_FILE_PATTERNS = # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. PREDEFINED = CC_FUNCTION_POINTER_ARGS:=1 \ - NETSTACK_CONF_WITH_RIME:=1 \ - NETSTACK_CONF_WITH_IPV4:=1 \ NETSTACK_CONF_WITH_IPV6:=1 \ - UIP_CONF_IPV6_RPL:=1 \ UIP_TCP:=1 \ UIP_UDP:=1 \ UIP_CONF_ICMP6:=1 \ diff --git a/tools/doxygen/modules.txt b/tools/doxygen/modules.txt index 7ece82e8b2fbdb661e48708a2d2d9c1184acfae2..635bbe1488f036acb667bc8fcacb5844fc52a255 100644 --- a/tools/doxygen/modules.txt +++ b/tools/doxygen/modules.txt @@ -8,36 +8,6 @@ CPU, device drivers and platform code * \ingroup arch */ -/** - * \addtogroup cc2538dk The cc2538 Development Kit platform - * \ingroup platform - */ - -/** - * \addtogroup cooja COOJA network simulator node - * \ingroup platform - */ - -/** - * \addtogroup exp5438 MSP430F5438 Experimenter Board - * \ingroup platform - */ - -/** - * \addtogroup jn516x The JN516x Board - * \ingroup platform - */ - -/** - * \addtogroup native_platform Native platform - * \ingroup platform - */ - -/** - * \addtogroup nrf52dk nRF52 Development Kit - * \ingroup platform - */ - /** \defgroup net IoT networking The communication protocols @@ -89,18 +59,13 @@ Core system components such as processes and timers */ /** -\defgroup dev CPUs and Device driver +\defgroup cpu CPUs \ingroup arch */ /** -* \defgroup arm ARM CPUs -* \ingroup dev -*/ - -/** -* \addtogroup nrf52832 nrf52832 SoC -* \ingroup dev +\defgroup dev Device Drivers +\ingroup arch */ /** diff --git a/tools/ip64/jool-start.sh b/tools/ip64/jool-start.sh new file mode 100755 index 0000000000000000000000000000000000000000..b9c0c9850e75661b02e8d7087fd8ea5419320923 --- /dev/null +++ b/tools/ip64/jool-start.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +defaultInterface=$(route | grep default | awk '{print $(NF)}') +myIP=$(ifconfig $defaultInterface | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}') +echo "Configuring jool for $myIP" + +sudo sysctl -w net.ipv4.conf.all.forwarding=1 +sudo sysctl -w net.ipv6.conf.all.forwarding=1 + +sudo /sbin/modprobe jool pool6=64:ff9b::/96 disabled + +# Assuming that we are on this IP +sudo jool -4 --add $myIP 15000-25000 +sudo jool --enable diff --git a/tools/jn516x/Makefile b/tools/jn516x/Makefile index be3caa44bfe43d9011b71ed1802bcdd9ee4fe4b1..2c4254a715fa8ab02194bc16b9eda57d1e66ecfd 100644 --- a/tools/jn516x/Makefile +++ b/tools/jn516x/Makefile @@ -21,5 +21,10 @@ endif all: $(SERIALDUMP) +CFLAGS += -Wall -Werror + $(SERIALDUMP): serialdump.c $(CC) -O2 -o $@ $< + +clean: + rm -f $(SERIALDUMP) diff --git a/tools/sky/Makefile b/tools/sky/Makefile index be3caa44bfe43d9011b71ed1802bcdd9ee4fe4b1..2c4254a715fa8ab02194bc16b9eda57d1e66ecfd 100644 --- a/tools/sky/Makefile +++ b/tools/sky/Makefile @@ -21,5 +21,10 @@ endif all: $(SERIALDUMP) +CFLAGS += -Wall -Werror + $(SERIALDUMP): serialdump.c $(CC) -O2 -o $@ $< + +clean: + rm -f $(SERIALDUMP) diff --git a/tools/sky/check-size b/tools/sky/check-size index fc0bb94293d39446d7bd0890f532e5ecd92b7e87..99a8c625749113f0b515b4f64ee83edb0a13866c 100755 --- a/tools/sky/check-size +++ b/tools/sky/check-size @@ -9,7 +9,6 @@ @sky = ( "battery-sensor", "button-sensor", "cfs-xmem", "clock", "contiki-sky-main", "ds2411", "flash", "msp430", - "mtarch", "i2c", "leds-arch", "light", "radio-sensor", "sht11", "simple-cc2420-arch", "simple-cc2420", "spi", "slip", "uart1", "watchdog", "xmem", "rtimer-arch" ); diff --git a/tools/sky/uip6-bridge/Makefile b/tools/sky/uip6-bridge/Makefile index ce605851e58638911548d78d7bf422c62fd59a79..55da6798e933a9da262f94f23f71a2730bd75d16 100644 --- a/tools/sky/uip6-bridge/Makefile +++ b/tools/sky/uip6-bridge/Makefile @@ -12,7 +12,7 @@ ifndef TARGET TARGET=sky endif -PROJECTDIRS = dev +MODULES_REL += dev PROJECT_SOURCEFILES = fakeuip.c sicslow_ethernet.c all: uip6-bridge-tap.sky diff --git a/tools/tapslip6.c b/tools/tapslip6.c deleted file mode 100644 index 86fa37dae787b8a6a29c85e2205771bb56fe76fc..0000000000000000000000000000000000000000 --- a/tools/tapslip6.c +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Copyright (c) 2001, Adam Dunkels. - * Copyright (c) 2009, Joakim Eriksson, Niclas Finne. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This file is part of the uIP TCP/IP stack. - * - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <time.h> -#include <sys/types.h> - -#include <unistd.h> -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <termios.h> -#include <sys/ioctl.h> - -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <err.h> - -in_addr_t giaddr; -in_addr_t netaddr; -in_addr_t circuit_addr; - -int ssystem(const char *fmt, ...) - __attribute__((__format__ (__printf__, 1, 2))); -void write_to_serial(int outfd, void *inbuf, int len); - -//#define PROGRESS(s) fprintf(stderr, s) -#define PROGRESS(s) do { } while (0) - -#define USAGE_STRING "usage: tapslip6 [-B baudrate] [-s siodev] [-t tundev] ipaddress netmask" - -char tundev[1024] = { "tap0" }; - -int -ssystem(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2))); - -int -ssystem(const char *fmt, ...) -{ - char cmd[128]; - va_list ap; - va_start(ap, fmt); - vsnprintf(cmd, sizeof(cmd), fmt, ap); - va_end(ap); - printf("%s\n", cmd); - fflush(stdout); - return system(cmd); -} - -#define SLIP_END 0300 -#define SLIP_ESC 0333 -#define SLIP_ESC_END 0334 -#define SLIP_ESC_ESC 0335 - -static void -print_packet(u_int8_t *p, int len) { - int i; - for(i = 0; i < len; i++) { - printf("%02x", p[i]); - if ((i & 3) == 3) - printf(" "); - if ((i & 15) == 15) - printf("\n"); - } - printf("\n"); -} - -int -is_sensible_string(const unsigned char *s, int len) -{ - int i; - for(i = 1; i < len; i++) { - if(s[i] == 0 || s[i] == '\r' || s[i] == '\n' || s[i] == '\t') { - continue; - } else if(s[i] < ' ' || '~' < s[i]) { - return 0; - } - } - return 1; -} - - - -/* - * Read from serial, when we have a packet write it to tun. No output - * buffering, input buffered by stdio. - */ -void -serial_to_tun(FILE *inslip, int outfd) -{ - static union { - unsigned char inbuf[2000]; - } uip; - static int inbufptr = 0; - - int ret; - unsigned char c; - -#ifdef linux - ret = fread(&c, 1, 1, inslip); - if(ret == -1 || ret == 0) err(1, "serial_to_tun: read"); - goto after_fread; -#endif - - read_more: - if(inbufptr >= sizeof(uip.inbuf)) { - inbufptr = 0; - } - ret = fread(&c, 1, 1, inslip); -#ifdef linux - after_fread: -#endif - if(ret == -1) { - err(1, "serial_to_tun: read"); - } - if(ret == 0) { - clearerr(inslip); - return; - fprintf(stderr, "serial_to_tun: EOF\n"); - exit(1); - } - /* fprintf(stderr, ".");*/ - switch(c) { - case SLIP_END: - if(inbufptr > 0) { - if(uip.inbuf[0] == '!') { - if (uip.inbuf[1] == 'M') { - /* Read gateway MAC address and autoconfigure tap0 interface */ - char macs[24]; - int i, pos; - for(i = 0, pos = 0; i < 16; i++) { - macs[pos++] = uip.inbuf[2 + i]; - if ((i & 1) == 1 && i < 14) { - macs[pos++] = ':'; - } - } - macs[pos] = '\0'; - printf("*** Gateway's MAC address: %s\n", macs); - - ssystem("ifconfig %s down", tundev); - ssystem("ifconfig %s hw ether %s", tundev, &macs[6]); - ssystem("ifconfig %s up", tundev); - } -#define DEBUG_LINE_MARKER '\r' - } else if(uip.inbuf[0] == DEBUG_LINE_MARKER) { - fwrite(uip.inbuf + 1, inbufptr - 1, 1, stdout); - } else if(is_sensible_string(uip.inbuf, inbufptr)) { - fwrite(uip.inbuf, inbufptr, 1, stdout); - } else { - printf("Writing to tun len: %d\n", inbufptr); - /* print_packet(uip.inbuf, inbufptr);*/ - if(write(outfd, uip.inbuf, inbufptr) != inbufptr) { - err(1, "serial_to_tun: write"); - } - } - inbufptr = 0; - } - break; - - case SLIP_ESC: - if(fread(&c, 1, 1, inslip) != 1) { - clearerr(inslip); - /* Put ESC back and give up! */ - ungetc(SLIP_ESC, inslip); - return; - } - - switch(c) { - case SLIP_ESC_END: - c = SLIP_END; - break; - case SLIP_ESC_ESC: - c = SLIP_ESC; - break; - } - /* FALLTHROUGH */ - default: - uip.inbuf[inbufptr++] = c; - break; - } - - goto read_more; -} - -unsigned char slip_buf[2000]; -int slip_end, slip_begin; - - -void -slip_send(int fd, unsigned char c) -{ - if (slip_end >= sizeof(slip_buf)) - err(1, "slip_send overflow"); - slip_buf[slip_end] = c; - slip_end++; -} - -int -slip_empty() -{ - return slip_end == 0; -} - -void -slip_flushbuf(int fd) -{ - int n; - - if (slip_empty()) - return; - - n = write(fd, slip_buf + slip_begin, (slip_end - slip_begin)); - - if(n == -1 && errno != EAGAIN) { - err(1, "slip_flushbuf write failed"); - } else if(n == -1) { - PROGRESS("Q"); /* Outqueueis full! */ - } else { - slip_begin += n; - if(slip_begin == slip_end) { - slip_begin = slip_end = 0; - } - } -} - -void -write_to_serial(int outfd, void *inbuf, int len) -{ - u_int8_t *p = inbuf; - int i, ecode; - - /* printf("Got packet of length %d - write SLIP\n", len);*/ - /* print_packet(p, len);*/ - - /* It would be ``nice'' to send a SLIP_END here but it's not - * really necessary. - */ - /* slip_send(outfd, SLIP_END); */ - /* printf("writing packet to serial!!! %d\n", len);*/ - for(i = 0; i < len; i++) { - switch(p[i]) { - case SLIP_END: - slip_send(outfd, SLIP_ESC); - slip_send(outfd, SLIP_ESC_END); - break; - case SLIP_ESC: - slip_send(outfd, SLIP_ESC); - slip_send(outfd, SLIP_ESC_ESC); - break; - default: - slip_send(outfd, p[i]); - break; - } - - } - slip_send(outfd, SLIP_END); - PROGRESS("t"); -} - - -/* - * Read from tun, write to slip. - */ -void -tun_to_serial(int infd, int outfd) -{ - struct { - unsigned char inbuf[2000]; - } uip; - int size; - - if((size = read(infd, uip.inbuf, 2000)) == -1) err(1, "tun_to_serial: read"); - - write_to_serial(outfd, uip.inbuf, size); -} - -#ifndef BAUDRATE -#define BAUDRATE B115200 -#endif -speed_t b_rate = BAUDRATE; - -void -stty_telos(int fd) -{ - struct termios tty; - speed_t speed = b_rate; - int i; - - if(tcflush(fd, TCIOFLUSH) == -1) err(1, "tcflush"); - - if(tcgetattr(fd, &tty) == -1) err(1, "tcgetattr"); - - cfmakeraw(&tty); - - /* Nonblocking read. */ - tty.c_cc[VTIME] = 0; - tty.c_cc[VMIN] = 0; - tty.c_cflag &= ~CRTSCTS; - tty.c_cflag &= ~HUPCL; - tty.c_cflag &= ~CLOCAL; - - cfsetispeed(&tty, speed); - cfsetospeed(&tty, speed); - - if(tcsetattr(fd, TCSAFLUSH, &tty) == -1) err(1, "tcsetattr"); - -#if 1 - /* Nonblocking read and write. */ - /* if(fcntl(fd, F_SETFL, O_NONBLOCK) == -1) err(1, "fcntl"); */ - - tty.c_cflag |= CLOCAL; - if(tcsetattr(fd, TCSAFLUSH, &tty) == -1) err(1, "tcsetattr"); - - i = TIOCM_DTR; - if(ioctl(fd, TIOCMBIS, &i) == -1) err(1, "ioctl"); -#endif - - usleep(10*1000); /* Wait for hardware 10ms. */ - - /* Flush input and output buffers. */ - if(tcflush(fd, TCIOFLUSH) == -1) err(1, "tcflush"); -} - -int -devopen(const char *dev, int flags) -{ - char t[1024]; - strcpy(t, "/dev/"); - strcat(t, dev); - return open(t, flags); -} - -#ifdef linux -#include <linux/if.h> -#include <linux/if_tun.h> - -int -tun_alloc(char *dev) -{ - struct ifreq ifr; - int fd, err; - - if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) - return -1; - - memset(&ifr, 0, sizeof(ifr)); - - /* Flags: IFF_TUN - TUN device (no Ethernet headers) - * IFF_TAP - TAP device - * - * IFF_NO_PI - Do not provide packet information - */ - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - if(*dev != 0) - strncpy(ifr.ifr_name, dev, IFNAMSIZ); - - if((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){ - close(fd); - return err; - } - strcpy(dev, ifr.ifr_name); - return fd; -} -#else -int -tun_alloc(char *dev) -{ - return devopen(dev, O_RDWR); -} -#endif - -const char *ipaddr; -const char *netmask; - -void -cleanup(void) -{ - ssystem("ifconfig %s down", tundev); -#ifndef linux - ssystem("sysctl -w net.ipv6.conf.all.forwarding=1"); -#endif - /* ssystem("arp -d %s", ipaddr); */ - ssystem("netstat -nr" - " | awk '{ if ($2 == \"%s\") print \"route delete -net \"$1; }'" - " | sh", - tundev); -} - -void -sigcleanup(int signo) -{ - fprintf(stderr, "signal %d\n", signo); - exit(0); /* exit(0) will call cleanup() */ -} - -static int got_sigalarm; -static int request_mac; - -void -sigalarm(int signo) -{ - got_sigalarm = 1; - return; -} - -void -sigalarm_reset() -{ -#ifdef linux -#define TIMEOUT (997*1000) -#else -#define TIMEOUT (2451*1000) -#endif - ualarm(TIMEOUT, TIMEOUT); - got_sigalarm = 0; -} - -void -ifconf(const char *tundev, const char *ipaddr, const char *netmask) -{ - struct in_addr netname; - netname.s_addr = inet_addr(ipaddr) & inet_addr(netmask); - -#ifdef linux - ssystem("ifconfig %s inet `hostname` up", tundev); - if(strcmp(ipaddr, "0.0.0.0") != 0) { - ssystem("route add -net %s netmask %s dev %s", - inet_ntoa(netname), netmask, tundev); - } -#else - ssystem("ifconfig %s inet `hostname` %s up", tundev, ipaddr); - if(strcmp(ipaddr, "0.0.0.0") != 0) { - ssystem("route add -net %s -netmask %s -interface %s", - inet_ntoa(netname), netmask, tundev); - } - ssystem("sysctl -w net.inet.ip.forwarding=1"); -#endif /* !linux */ - - ssystem("ifconfig %s\n", tundev); -} - -int -main(int argc, char **argv) -{ - int c; - int tunfd, slipfd, maxfd; - int ret; - fd_set rset, wset; - FILE *inslip; - const char *siodev = NULL; - int baudrate = -2; - request_mac = 1; - setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */ - - while((c = getopt(argc, argv, "B:D:hs:t:")) != -1) { - switch (c) { - case 'B': - baudrate = atoi(optarg); - break; - - case 's': - if(strncmp("/dev/", optarg, 5) == 0) { - siodev = optarg + 5; - } else { - siodev = optarg; - } - break; - - case 't': - if(strncmp("/dev/", optarg, 5) == 0) { - strcpy(tundev, optarg + 5); - } else { - strcpy(tundev, optarg); - } - break; - - case '?': - case 'h': - default: - errx(1, USAGE_STRING); - break; - } - } - argc -= (optind - 1); - argv += (optind - 1); - - if(argc != 3 && argc != 4) { - errx(1, USAGE_STRING); - } - ipaddr = argv[1]; - netmask = argv[2]; - circuit_addr = inet_addr(ipaddr); - netaddr = inet_addr(ipaddr) & inet_addr(netmask); - - switch(baudrate) { - case -2: - break; /* Use default. */ - case 9600: - b_rate = B9600; - break; - case 19200: - b_rate = B19200; - break; - case 38400: - b_rate = B38400; - break; - case 57600: - b_rate = B57600; - break; - case 115200: - b_rate = B115200; - break; - default: - err(1, "unknown baudrate %d", baudrate); - break; - } - - - if(siodev != NULL) { - slipfd = devopen(siodev, O_RDWR | O_NONBLOCK); - if(slipfd == -1) { - err(1, "can't open siodev ``/dev/%s''", siodev); - } - } else { - static const char *siodevs[] = { - "ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */ - }; - int i; - for(i = 0; i < 3; i++) { - siodev = siodevs[i]; - slipfd = devopen(siodev, O_RDWR | O_NONBLOCK); - if (slipfd != -1) - break; - } - if(slipfd == -1) { - err(1, "can't open siodev"); - } - } - fprintf(stderr, "slip started on ``/dev/%s''\n", siodev); - stty_telos(slipfd); - slip_send(slipfd, SLIP_END); - inslip = fdopen(slipfd, "r"); - if(inslip == NULL) err(1, "main: fdopen"); - - tunfd = tun_alloc(tundev); - printf("opening: %s", tundev); - if(tunfd == -1) err(1, "main: open"); - fprintf(stderr, "opened device ``/dev/%s''\n", tundev); - - atexit(cleanup); - signal(SIGHUP, sigcleanup); - signal(SIGTERM, sigcleanup); - signal(SIGINT, sigcleanup); - signal(SIGALRM, sigalarm); - ifconf(tundev, ipaddr, netmask); - - while(1) { - maxfd = 0; - FD_ZERO(&rset); - FD_ZERO(&wset); - - /* request mac address from gateway node for autoconfiguration of - ethernet interface tap0 */ - if (request_mac) { - slip_send(slipfd, '?'); - slip_send(slipfd, 'M'); - slip_send(slipfd, SLIP_END); - request_mac = 0; - } - - if(got_sigalarm) { - /* Send "?IPA". */ - slip_send(slipfd, '?'); - slip_send(slipfd, 'I'); - slip_send(slipfd, 'P'); - slip_send(slipfd, 'A'); - slip_send(slipfd, SLIP_END); - got_sigalarm = 0; - } - - if(!slip_empty()) { /* Anything to flush? */ - FD_SET(slipfd, &wset); - } - - FD_SET(slipfd, &rset); /* Read from slip ASAP! */ - if(slipfd > maxfd) maxfd = slipfd; - - /* We only have one packet at a time queued for slip output. */ - if(slip_empty()) { - FD_SET(tunfd, &rset); - if(tunfd > maxfd) maxfd = tunfd; - } - - ret = select(maxfd + 1, &rset, &wset, NULL, NULL); - if(ret == -1 && errno != EINTR) { - err(1, "select"); - } else if(ret > 0) { - if(FD_ISSET(slipfd, &rset)) { - serial_to_tun(inslip, tunfd); - } - - if(FD_ISSET(slipfd, &wset)) { - slip_flushbuf(slipfd); - sigalarm_reset(); - } - - if(slip_empty() && FD_ISSET(tunfd, &rset)) { - tun_to_serial(tunfd, slipfd); - slip_flushbuf(slipfd); - sigalarm_reset(); - } - } - } -} diff --git a/tools/tunslip.c b/tools/tunslip.c deleted file mode 100644 index 371418f539123e7909aa98d7c821cc969b8958da..0000000000000000000000000000000000000000 --- a/tools/tunslip.c +++ /dev/null @@ -1,1113 +0,0 @@ -/* - * Copyright (c) 2001, Adam Dunkels. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This file is part of the uIP TCP/IP stack. - * - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <time.h> -#include <sys/types.h> - -#include <unistd.h> -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <termios.h> -#include <sys/ioctl.h> - -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <err.h> - -int ssystem(const char *fmt, ...) - __attribute__((__format__ (__printf__, 1, 2))); -void write_to_serial(int outfd, void *inbuf, int len); - -//#define PROGRESS(s) fprintf(stderr, s) -#define PROGRESS(s) do { } while (0) - -struct ip { - u_int8_t ip_vhl; /* version and header length */ -#define IP_V4 0x40 -#define IP_V 0xf0 -#define IP_HL 0x0f - u_int8_t ip_tos; /* type of service */ - u_int16_t ip_len; /* total length */ - u_int16_t ip_id; /* identification */ - u_int16_t ip_off; /* fragment offset field */ -#define IP_RF 0x8000 /* reserved fragment flag */ -#define IP_DF 0x4000 /* dont fragment flag */ -#define IP_MF 0x2000 /* more fragments flag */ -#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ - u_int8_t ip_ttl; /* time to live */ - u_int8_t ip_p; /* protocol */ - u_int16_t ip_sum; /* checksum */ - u_int32_t ip_src, ip_dst; /* source and dest address */ - u_int16_t uh_sport; /* source port */ - u_int16_t uh_dport; /* destination port */ - u_int16_t uh_ulen; /* udp length */ - u_int16_t uh_sum; /* udp checksum */ -}; - -int check_ip(const struct ip *ip, unsigned ip_len); -u_int16_t ip4sum(u_int16_t sum, const void *_p, u_int16_t len); - -struct dhcp_msg { - u_int8_t op, htype, hlen, hops; - u_int8_t xid[4]; - u_int16_t secs, flags; - u_int8_t ciaddr[4]; - u_int8_t yiaddr[4]; - u_int8_t siaddr[4]; - u_int8_t giaddr[4]; - u_int8_t chaddr[16]; -#define DHCP_BASE_LEN (4*7 + 16) - u_int8_t sname[64]; - u_int8_t file[128]; -#define DHCP_HOLE_LEN (64 + 128) -#define DHCP_MSG_LEN (DHCP_BASE_LEN + DHCP_HOLE_LEN) - u_int8_t options[312]; -}; - -struct dhcp_light_msg { - u_int8_t op, htype, hlen, hops; - u_int8_t xid[4]; - u_int16_t secs, flags; - u_int8_t ciaddr[4]; - u_int8_t yiaddr[4]; - u_int8_t siaddr[4]; - u_int8_t giaddr[4]; - u_int8_t chaddr[16]; -#define DHCP_LIGHT_MSG_LEN (4*7 + 16) - u_int8_t options[312]; -}; - -#define DHCP_OPTION_SUBNET_MASK 1 -#define DHCP_OPTION_ROUTER 3 -#define DHCP_OPTION_DNS_SERVER 6 -#define DHCP_OPTION_REQ_IPADDR 50 -#define DHCP_OPTION_LEASE_TIME 51 -#define DHCP_OPTION_MSG_TYPE 53 -#define DHCP_OPTION_SERVER_ID 54 -#define DHCP_OPTION_REQ_LIST 55 -#define DHCP_OPTION_AGENT 82 -#define DHCP_OPTION_SUBNET_SELECTION 118 -#define DHCP_OPTION_END 255 - -/* DHCP_OPTION_AGENT, Relay Agent Information option subtypes: */ -#define RAI_CIRCUIT_ID 1 -#define RAI_REMOTE_ID 2 -#define RAI_AGENT_ID 3 -#define RAI_SUBNET_SELECTION 5 - -#define DHCPDISCOVER 1 -#define DHCPOFFER 2 -#define DHCPREQUEST 3 -#define DHCPDECLINE 4 -#define DHCPACK 5 -#define DHCPNAK 6 -#define DHCPRELEASE 7 - -#define BOOTP_BROADCAST 0x8000 - -#define BOOTPS 67 -#define BOOTPC 68 - -#define BOOTREQUEST 1 -#define BOOTREPLY 2 - -in_addr_t giaddr; -in_addr_t netaddr; -in_addr_t circuit_addr; - -char tundev[1024] = { "tun0" }; - -struct sockaddr_in dhaddr; -int dhsock = -1; - -void -relay_dhcp_to_server(struct ip *ip, int len) -{ - struct dhcp_light_msg *inm; - struct dhcp_msg m; - int n; - u_int8_t *optptr; - - inm = (void*)(((u_int8_t*)ip) + 20 + 8); /* Skip over IP&UDP headers. */ - - if (inm->op != BOOTREQUEST) { - return; - } - - inm->flags = ntohs(BOOTP_BROADCAST); - - memcpy(&m, inm, DHCP_BASE_LEN); - memset(&m.sname, 0x0, DHCP_HOLE_LEN); - memcpy(&m.options, &inm->options, len - 20 - 8 - DHCP_BASE_LEN); - n = (len - 20 - 8) + DHCP_HOLE_LEN; /* +HOLE -IP&UDP headers. */ - - /* - * Ideally we would like to use the Relay Agent information option - * (RFC3046) together with the Link Selection sub-option (RFC3527) - * to ensure that addresses are allocated for this - * subnet. Unfortunately ISC-DHCPD does not currently implement - * RFC3527 and some other mechanism must be used. For this reason - * this implementation in addition uses the DHCP option for subnet - * selection (RFC3011) which is really not intended to be used by - * relays. - * - * Find DHCP_OPTION_END and add the new option here. - */ - optptr = &m.options[n - DHCP_BASE_LEN - DHCP_HOLE_LEN - 1]; - { - *optptr++ = DHCP_OPTION_SUBNET_SELECTION; /* RFC3011 */ - *optptr++ = 4; - memcpy(optptr, &netaddr, 4); optptr += 4; - n += 4 + 2; - } - { - *optptr++ = DHCP_OPTION_AGENT; /* RFC3046 */ - *optptr++ = 18; /* Sum of all suboptions below! */ - - *optptr++ = RAI_SUBNET_SELECTION; /* RFC3527 */ - *optptr++ = 4; - memcpy(optptr, &netaddr, 4); optptr += 4; - *optptr++ = RAI_CIRCUIT_ID; - *optptr++ = 4; - memcpy(optptr, &circuit_addr, 4); optptr += 4; - *optptr++ = RAI_AGENT_ID; - *optptr++ = 4; - memcpy(optptr, &giaddr, 4); optptr += 4; - n += 18 + 2; /* Sum of all suboptions + 2! */ - } - /* And finally put back the END. */ - *optptr++ = DHCP_OPTION_END; - - m.hops++; - memcpy(m.giaddr, &giaddr, sizeof(m.giaddr)); - if (n != sendto(dhsock, &m, n, 0x0/*flags*/, - (struct sockaddr *)&dhaddr, sizeof(dhaddr))) - err(1, "sendto relay failed"); -} - -static u_int16_t ip_id; - -void -relay_dhcp_to_client(int slipfd) -{ - struct dhcp_msg inm; - struct { - struct ip ip; - struct dhcp_light_msg m; - } pkt; - int n, optlen, ip_len, udp_len; - u_int8_t *p, *t, *end; - u_int16_t sum; - u_int8_t op, msg_type = 0; - struct in_addr yiaddr; - - memset(&inm.options, 0x0, sizeof(inm.options)); - - n = recv(dhsock, &inm, sizeof(inm), 0x0/*flags*/); - - if (inm.op != BOOTREPLY) { - return; - } - - memcpy(&yiaddr, inm.yiaddr, sizeof(inm.yiaddr)); - memcpy(&pkt.m, &inm, DHCP_BASE_LEN); - pkt.m.hops++; - memset(pkt.m.giaddr, 0x0, sizeof(pkt.m.giaddr)); - - /* - * Copy options we would like to send to client. - */ - memcpy(pkt.m.options, inm.options, 4); /* Magic cookie */ - - end = &inm.op + n; - p = inm.options + 4; /* Magic cookie */ - t = pkt.m.options + 4; /* Magic cookie */ - while (p < end) { - op = p[0]; - switch (op) { - case DHCP_OPTION_END: - goto done; - - case DHCP_OPTION_MSG_TYPE: - msg_type = p[2]; - case DHCP_OPTION_SUBNET_MASK: - case DHCP_OPTION_ROUTER: - case DHCP_OPTION_LEASE_TIME: - case DHCP_OPTION_SERVER_ID: /* Copy these options */ - memcpy(t, p, p[1] + 2); - t += p[1] + 2; - p += p[1] + 2; - break; - - case DHCP_OPTION_DNS_SERVER: /* Only copy first server */ - *t++ = p[0]; - *t++ = 4; - memcpy(t, p + 2, 4); t += 4; - p += p[1] + 2; - break; - - default: /* Ignore these options */ - /* printf("option type %d len %d\n", op, p[1]); */ - p += p[1] + 2; - continue; - } - } - done: - if (op == DHCP_OPTION_END) { - *t++ = op; *p++; - } - - optlen = t - pkt.m.options; - ip_len = 20 + 8 + DHCP_BASE_LEN + optlen; - udp_len = 8 + DHCP_BASE_LEN + optlen; - - pkt.ip.ip_vhl = 0x45; /* IPv4 and hdrlen=5*4 */ - pkt.ip.ip_tos = 0; - pkt.ip.ip_len = htons(ip_len); - pkt.ip.ip_id = htons(ip_id++); - pkt.ip.ip_off = 0; - pkt.ip.ip_ttl = 64; - pkt.ip.ip_p = 17; /* proto UDP */ - pkt.ip.ip_sum = 0; - pkt.ip.ip_src = giaddr; - if (inm.flags & htons(BOOTP_BROADCAST)) /* check bcast bit */ - pkt.ip.ip_dst = 0xffffffff; /* 255.255.255.255 */ - else - pkt.ip.ip_dst = yiaddr.s_addr; - - pkt.ip.uh_sport = htons(BOOTPS); - pkt.ip.uh_dport = htons(BOOTPC); - pkt.ip.uh_ulen = htons(udp_len); - pkt.ip.uh_sum = 0; - - pkt.ip.ip_sum = ~htons(ip4sum(0, &pkt.ip, 20)); - sum = 17 + udp_len; - sum = ip4sum(sum, &pkt.ip.ip_src, 8); - sum = ip4sum(sum, &pkt.ip.uh_sport, udp_len); - if (sum != 0xffff) - pkt.ip.uh_sum = ~htons(sum); - else - pkt.ip.uh_sum = 0xffff; - - write_to_serial(slipfd, &pkt, ip_len); - if (msg_type == DHCPACK) { - printf("DHCPACK %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x IP %s\n", - pkt.m.chaddr[0], pkt.m.chaddr[1], pkt.m.chaddr[2], pkt.m.chaddr[3], - pkt.m.chaddr[4], pkt.m.chaddr[5], pkt.m.chaddr[6], pkt.m.chaddr[7], - inet_ntoa(yiaddr)); - /* ssystem("arp -s %s auto pub only", inet_ntoa(yiaddr)); */ - } -} - -/* - * Internet checksum in host byte order. - */ -u_int16_t -ip4sum(u_int16_t sum, const void *_p, u_int16_t len) -{ - u_int16_t t; - const u_int8_t *p = _p; - const u_int8_t *end = p + len; - - while(p < (end-1)) { - t = (p[0] << 8) + p[1]; - sum += t; - if (sum < t) sum++; - p += 2; - } - if(p < end) { - t = (p[0] << 8) + 0; - sum += t; - if (sum < t) sum++; - } - return sum; -} - -int -check_ip(const struct ip *ip, unsigned ip_len) -{ - u_int16_t sum, ip_hl; - - /* Check IP version and length. */ - if((ip->ip_vhl & IP_V) != IP_V4) - return -1; - - if(ntohs(ip->ip_len) > ip_len) - return -2; - - if(ntohs(ip->ip_len) < ip_len) - return -3; - - /* Check IP header. */ - ip_hl = 4*(ip->ip_vhl & IP_HL); - sum = ip4sum(0, ip, ip_hl); - if(sum != 0xffff && sum != 0x0) - return -4; - - if(ip->ip_p == 6 || ip->ip_p == 17) { /* Check TCP or UDP header. */ - u_int16_t tcp_len = ip_len - ip_hl; - - /* Sum pseudoheader. */ - sum = ip->ip_p + tcp_len; /* proto and len, no carry */ - sum = ip4sum(sum, &ip->ip_src, 8); /* src and dst */ - - /* Sum TCP/UDP header and data. */ - sum = ip4sum(sum, (u_int8_t*)ip + ip_hl, tcp_len); - - /* Failed checksum test? */ - if (sum != 0xffff && sum != 0x0) { - if (ip->ip_p == 6) { /* TCP == 6 */ - return -5; - } else { /* UDP */ - /* Deal with disabled UDP checksums. */ - if (ip->uh_sum != 0) - return -6; - } - } - } else if (ip->ip_p == 1) { /* ICMP */ - u_int16_t icmp_len = ip_len - ip_hl; - - sum = ip4sum(0, (u_int8_t*)ip + ip_hl, icmp_len); - if(sum != 0xffff && sum != 0x0) - return -7; - } - return 0; -} - -int -is_sensible_string(const unsigned char *s, int len) -{ - int i; - for(i = 1; i < len; i++) { - if(s[i] == 0 || s[i] == '\r' || s[i] == '\n' || s[i] == '\t') { - continue; - } else if(s[i] < ' ' || '~' < s[i]) { - return 0; - } - } - return 1; -} - -int -ssystem(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2))); - -int -ssystem(const char *fmt, ...) -{ - char cmd[128]; - va_list ap; - va_start(ap, fmt); - vsnprintf(cmd, sizeof(cmd), fmt, ap); - va_end(ap); - printf("%s\n", cmd); - fflush(stdout); - return system(cmd); -} - -#define SLIP_END 0300 -#define SLIP_ESC 0333 -#define SLIP_ESC_END 0334 -#define SLIP_ESC_ESC 0335 - -/* - * Read from serial, when we have a packet write it to tun. No output - * buffering, input buffered by stdio. - */ -void -serial_to_tun(FILE *inslip, int outfd) -{ - static union { - unsigned char inbuf[2000]; - struct ip iphdr; - } uip; - static int inbufptr = 0; - - int ret; - unsigned char c; - -#ifdef linux - ret = fread(&c, 1, 1, inslip); - if(ret == -1 || ret == 0) err(1, "serial_to_tun: read"); - goto after_fread; -#endif - - read_more: - if(inbufptr >= sizeof(uip.inbuf)) { - inbufptr = 0; - } - ret = fread(&c, 1, 1, inslip); -#ifdef linux - after_fread: -#endif - if(ret == -1) { - err(1, "serial_to_tun: read"); - } - if(ret == 0) { - clearerr(inslip); - return; - fprintf(stderr, "serial_to_tun: EOF\n"); - exit(1); - } - /* fprintf(stderr, ".");*/ - switch(c) { - case SLIP_END: - if(inbufptr > 0) { - /* - * Sanity checks. - */ -#define DEBUG_LINE_MARKER '\r' - int ecode; - ecode = check_ip(&uip.iphdr, inbufptr); - if(ecode < 0 && inbufptr == 8 && strncmp(uip.inbuf, "=IPA", 4) == 0) { - static struct in_addr ipa; - - inbufptr = 0; - if(memcmp(&ipa, &uip.inbuf[4], sizeof(ipa)) == 0) { - break; - } - - /* New address. */ - if(ipa.s_addr != 0) { -#ifdef linux - ssystem("route delete -net %s netmask %s dev %s", - inet_ntoa(ipa), "255.255.255.255", tundev); -#else - ssystem("route delete -net %s -netmask %s -interface %s", - inet_ntoa(ipa), "255.255.255.255", tundev); -#endif - } - - memcpy(&ipa, &uip.inbuf[4], sizeof(ipa)); - if(ipa.s_addr != 0) { -#ifdef linux - ssystem("route add -net %s netmask %s dev %s", - inet_ntoa(ipa), "255.255.255.255", tundev); -#else - ssystem("route add -net %s -netmask %s -interface %s", - inet_ntoa(ipa), "255.255.255.255", tundev); -#endif - } - break; - } else if(ecode < 0) { - /* - * If sensible ASCII string, print it as debug info! - */ - if(uip.inbuf[0] == DEBUG_LINE_MARKER) { - fwrite(uip.inbuf + 1, inbufptr - 1, 1, stderr); - } else if(is_sensible_string(uip.inbuf, inbufptr)) { - fwrite(uip.inbuf, inbufptr, 1, stderr); - } else { - fprintf(stderr, - "serial_to_tun: drop packet len=%d ecode=%d\n", - inbufptr, ecode); - } - inbufptr = 0; - break; - } - PROGRESS("s"); - - if(dhsock != -1) { - struct ip *ip = (void *)uip.inbuf; - if(ip->ip_p == 17 && ip->ip_dst == 0xffffffff /* UDP and broadcast */ - && ip->uh_sport == ntohs(BOOTPC) && ip->uh_dport == ntohs(BOOTPS)) { - relay_dhcp_to_server(ip, inbufptr); - inbufptr = 0; - } - } - if(write(outfd, uip.inbuf, inbufptr) != inbufptr) { - err(1, "serial_to_tun: write"); - } - inbufptr = 0; - } - break; - - case SLIP_ESC: - if(fread(&c, 1, 1, inslip) != 1) { - clearerr(inslip); - /* Put ESC back and give up! */ - ungetc(SLIP_ESC, inslip); - return; - } - - switch(c) { - case SLIP_ESC_END: - c = SLIP_END; - break; - case SLIP_ESC_ESC: - c = SLIP_ESC; - break; - } - /* FALLTHROUGH */ - default: - uip.inbuf[inbufptr++] = c; - break; - } - - goto read_more; -} - -unsigned char slip_buf[2000]; -int slip_end, slip_begin; - -void -slip_send(int fd, unsigned char c) -{ - if (slip_end >= sizeof(slip_buf)) - err(1, "slip_send overflow"); - slip_buf[slip_end] = c; - slip_end++; -} - -int -slip_empty() -{ - return slip_end == 0; -} - -void -slip_flushbuf(int fd) -{ - int n; - - if (slip_empty()) - return; - - n = write(fd, slip_buf + slip_begin, (slip_end - slip_begin)); - - if(n == -1 && errno != EAGAIN) { - err(1, "slip_flushbuf write failed"); - } else if(n == -1) { - PROGRESS("Q"); /* Outqueueis full! */ - } else { - slip_begin += n; - if(slip_begin == slip_end) { - slip_begin = slip_end = 0; - } - } -} - -void -write_to_serial(int outfd, void *inbuf, int len) -{ - u_int8_t *p = inbuf; - int i, ecode; - struct ip *iphdr = inbuf; - - /* - * Sanity checks. - */ - ecode = check_ip(inbuf, len); - if(ecode < 0) { - fprintf(stderr, "tun_to_serial: drop packet %d\n", ecode); - return; - } - - if(iphdr->ip_id == 0 && iphdr->ip_off & IP_DF) { - uint16_t nid = htons(ip_id++); - iphdr->ip_id = nid; - nid = ~nid; /* negate */ - iphdr->ip_sum += nid; /* add */ - if(iphdr->ip_sum < nid) { /* 1-complement overflow? */ - iphdr->ip_sum++; - } - ecode = check_ip(inbuf, len); - if(ecode < 0) { - fprintf(stderr, "tun_to_serial: drop packet %d\n", ecode); - return; - } - } - - /* It would be ``nice'' to send a SLIP_END here but it's not - * really necessary. - */ - /* slip_send(outfd, SLIP_END); */ - - for(i = 0; i < len; i++) { - switch(p[i]) { - case SLIP_END: - slip_send(outfd, SLIP_ESC); - slip_send(outfd, SLIP_ESC_END); - break; - case SLIP_ESC: - slip_send(outfd, SLIP_ESC); - slip_send(outfd, SLIP_ESC_ESC); - break; - default: - slip_send(outfd, p[i]); - break; - } - - } - slip_send(outfd, SLIP_END); - PROGRESS("t"); -} - - -/* - * Read from tun, write to slip. - */ -void -tun_to_serial(int infd, int outfd) -{ - static union { - unsigned char inbuf[2000]; - struct ip iphdr; - } uip; - int size; - - if((size = read(infd, uip.inbuf, 2000)) == -1) err(1, "tun_to_serial: read"); - - write_to_serial(outfd, uip.inbuf, size); -} - -#ifndef BAUDRATE -#define BAUDRATE B115200 -#endif -speed_t b_rate = BAUDRATE; - -void -stty_telos(int fd) -{ - struct termios tty; - speed_t speed = b_rate; - int i; - - if(tcflush(fd, TCIOFLUSH) == -1) err(1, "tcflush"); - - if(tcgetattr(fd, &tty) == -1) err(1, "tcgetattr"); - - cfmakeraw(&tty); - - /* Nonblocking read. */ - tty.c_cc[VTIME] = 0; - tty.c_cc[VMIN] = 0; - tty.c_cflag &= ~CRTSCTS; - tty.c_cflag &= ~HUPCL; - tty.c_cflag &= ~CLOCAL; - - cfsetispeed(&tty, speed); - cfsetospeed(&tty, speed); - - if(tcsetattr(fd, TCSAFLUSH, &tty) == -1) err(1, "tcsetattr"); - -#if 1 - /* Nonblocking read and write. */ - /* if(fcntl(fd, F_SETFL, O_NONBLOCK) == -1) err(1, "fcntl"); */ - - tty.c_cflag |= CLOCAL; - if(tcsetattr(fd, TCSAFLUSH, &tty) == -1) err(1, "tcsetattr"); - - i = TIOCM_DTR; - if(ioctl(fd, TIOCMBIS, &i) == -1) err(1, "ioctl"); -#endif - - usleep(10*1000); /* Wait for hardware 10ms. */ - - /* Flush input and output buffers. */ - if(tcflush(fd, TCIOFLUSH) == -1) err(1, "tcflush"); -} - -int -devopen(const char *dev, int flags) -{ - char t[1024]; - strcpy(t, "/dev/"); - strcat(t, dev); - return open(t, flags); -} - -#ifdef linux -#include <linux/if.h> -#include <linux/if_tun.h> - -int -tun_alloc(char *dev) -{ - struct ifreq ifr; - int fd, err; - - if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) - return -1; - - memset(&ifr, 0, sizeof(ifr)); - - /* Flags: IFF_TUN - TUN device (no Ethernet headers) - * IFF_TAP - TAP device - * - * IFF_NO_PI - Do not provide packet information - */ - ifr.ifr_flags = IFF_TUN | IFF_NO_PI; - if(*dev != 0) - strncpy(ifr.ifr_name, dev, IFNAMSIZ); - - if((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){ - close(fd); - return err; - } - strcpy(dev, ifr.ifr_name); - return fd; -} -#else -int -tun_alloc(char *dev) -{ - return devopen(dev, O_RDWR); -} -#endif - -const char *ipaddr; -const char *netmask; - -void -cleanup(void) -{ - ssystem("ifconfig %s down", tundev); -#ifndef linux - ssystem("sysctl -w net.inet.ip.forwarding=0"); -#endif - /* ssystem("arp -d %s", ipaddr); */ - ssystem("netstat -nr" - " | awk '{ if ($2 == \"%s\") print \"route delete -net \"$1; }'" - " | sh", - tundev); -} - -void -sigcleanup(int signo) -{ - fprintf(stderr, "signal %d\n", signo); - exit(0); /* exit(0) will call cleanup() */ -} - -static int got_sigalarm; - -void -sigalarm(int signo) -{ - got_sigalarm = 1; - return; -} - -void -sigalarm_reset() -{ -#ifdef linux -#define TIMEOUT (997*1000) -#else -#define TIMEOUT (2451*1000) -#endif - ualarm(TIMEOUT, TIMEOUT); - got_sigalarm = 0; -} - -void -ifconf(const char *tundev, const char *ipaddr, const char *netmask) -{ - struct in_addr netname; - netname.s_addr = inet_addr(ipaddr) & inet_addr(netmask); - -#ifdef linux - ssystem("ifconfig %s inet `hostname` up", tundev); - if(strcmp(ipaddr, "0.0.0.0") != 0) { - ssystem("route add -net %s netmask %s dev %s", - inet_ntoa(netname), netmask, tundev); - } -#else - ssystem("ifconfig %s inet `hostname` %s up", tundev, ipaddr); - if(strcmp(ipaddr, "0.0.0.0") != 0) { - ssystem("route add -net %s -netmask %s -interface %s", - inet_ntoa(netname), netmask, tundev); - } - ssystem("sysctl -w net.inet.ip.forwarding=1"); -#endif /* !linux */ - - ssystem("ifconfig %s\n", tundev); -} - -int -main(int argc, char **argv) -{ - int c; - int tunfd, slipfd, maxfd; - int ret; - fd_set rset, wset; - FILE *inslip; - const char *siodev = NULL; - const char *dhcp_server = NULL; - u_int16_t myport = BOOTPS, dhport = BOOTPS; - int baudrate = -2; - - ip_id = getpid() * time(NULL); - - setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */ - - while((c = getopt(argc, argv, "B:D:hs:t:")) != -1) { - switch (c) { - case 'B': - baudrate = atoi(optarg); - break; - - case 'D': - dhcp_server = optarg; - break; - - case 's': - if(strncmp("/dev/", optarg, 5) == 0) { - siodev = optarg + 5; - } else { - siodev = optarg; - } - break; - - case 't': - if(strncmp("/dev/", optarg, 5) == 0) { - strcpy(tundev, optarg + 5); - } else { - strcpy(tundev, optarg); - } - break; - - case '?': - case 'h': - default: - err(1, "usage: tunslip [-B baudrate] [-s siodev] [-t tundev] [-D dhcp-server] ipaddress netmask [dhcp-server]"); - break; - } - } - argc -= (optind - 1); - argv += (optind - 1); - - if(argc != 3 && argc != 4) { - err(1, "usage: tunslip [-s siodev] [-t tundev] [-D dhcp-server] ipaddress netmask [dhcp-server]"); - } - ipaddr = argv[1]; - netmask = argv[2]; - circuit_addr = inet_addr(ipaddr); - netaddr = inet_addr(ipaddr) & inet_addr(netmask); - - switch(baudrate) { - case -2: - break; /* Use default. */ - case 9600: - b_rate = B9600; - break; - case 19200: - b_rate = B19200; - break; - case 38400: - b_rate = B38400; - break; - case 57600: - b_rate = B57600; - break; - case 115200: - b_rate = B115200; - break; - default: - err(1, "unknown baudrate %d", baudrate); - break; - } - - /* - * Set up DHCP relay agent socket and find the address of this relay - * agent. - */ - if(argc == 4) { - dhcp_server = argv[3]; - } - if(dhcp_server != NULL) { - struct sockaddr_in myaddr; - socklen_t len; - in_addr_t a; - - if(strchr(dhcp_server, ':') != NULL) { - dhport = atoi(strchr(dhcp_server, ':') + 1); - myport = dhport + 1; - *strchr(dhcp_server, ':') = '\0'; - } - a = inet_addr(dhcp_server); - if(a == -1) { - err(1, "illegal dhcp-server address"); - } -#ifndef linux - dhaddr.sin_len = sizeof(dhaddr); -#endif - dhaddr.sin_family = AF_INET; - dhaddr.sin_port = htons(dhport); - dhaddr.sin_addr.s_addr = a; - - dhsock = socket(AF_INET, SOCK_DGRAM, 0); - if(dhsock < 0) { - err (1, "socket"); - } - memset(&myaddr, 0x0, sizeof(myaddr)); -#ifndef linux - myaddr.sin_len = sizeof(myaddr); -#endif - myaddr.sin_family = AF_INET; - myaddr.sin_addr.s_addr = INADDR_ANY; - myaddr.sin_port = htons(myport); - if(bind(dhsock, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { - err(1, "bind dhcp-relay"); - } - - if(connect(dhsock, (struct sockaddr *)&dhaddr, sizeof(dhaddr)) < 0) { - err(1, "connect to dhcp-server"); - } - - len = sizeof(myaddr); - if(getsockname(dhsock, (struct sockaddr *)&myaddr, &len) < 0) { - err(1, "getsockname dhsock"); - } - - giaddr = myaddr.sin_addr.s_addr; - - /* - * Don't want connected socket. - */ - close(dhsock); - dhsock = socket(AF_INET, SOCK_DGRAM, 0); - if(dhsock < 0) { - err (1, "socket"); - } - myaddr.sin_family = AF_INET; - myaddr.sin_addr.s_addr = INADDR_ANY; - myaddr.sin_port = htons(myport); - if(bind(dhsock, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { - err(1, "bind dhcp-relay"); - } - fprintf(stderr, "DHCP server at %s:%d\n", dhcp_server, dhport); - } - - if(siodev != NULL) { - slipfd = devopen(siodev, O_RDWR | O_NONBLOCK); - if(slipfd == -1) { - err(1, "can't open siodev ``/dev/%s''", siodev); - } - } else { - static const char *siodevs[] = { - "ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */ - }; - int i; - for(i = 0; i < 3; i++) { - siodev = siodevs[i]; - slipfd = devopen(siodev, O_RDWR | O_NONBLOCK); - if (slipfd != -1) - break; - } - if(slipfd == -1) { - err(1, "can't open siodev"); - } - } - fprintf(stderr, "slip started on ``/dev/%s''\n", siodev); - stty_telos(slipfd); - slip_send(slipfd, SLIP_END); - inslip = fdopen(slipfd, "r"); - if(inslip == NULL) err(1, "main: fdopen"); - - tunfd = tun_alloc(tundev); - if(tunfd == -1) err(1, "main: open"); - fprintf(stderr, "opened device ``/dev/%s''\n", tundev); - - atexit(cleanup); - signal(SIGHUP, sigcleanup); - signal(SIGTERM, sigcleanup); - signal(SIGINT, sigcleanup); - signal(SIGALRM, sigalarm); - ifconf(tundev, ipaddr, netmask); - - while(1) { - maxfd = 0; - FD_ZERO(&rset); - FD_ZERO(&wset); - - if(got_sigalarm) { - /* Send "?IPA". */ - slip_send(slipfd, '?'); - slip_send(slipfd, 'I'); - slip_send(slipfd, 'P'); - slip_send(slipfd, 'A'); - slip_send(slipfd, SLIP_END); - got_sigalarm = 0; - } - - if(!slip_empty()) { /* Anything to flush? */ - FD_SET(slipfd, &wset); - } - - FD_SET(slipfd, &rset); /* Read from slip ASAP! */ - if(slipfd > maxfd) maxfd = slipfd; - - /* We only have one packet at a time queued for slip output. */ - if(slip_empty()) { - FD_SET(tunfd, &rset); - if(tunfd > maxfd) maxfd = tunfd; - if(dhsock != -1) { - FD_SET(dhsock, &rset); - if(dhsock > maxfd) maxfd = dhsock; - } - } - - ret = select(maxfd + 1, &rset, &wset, NULL, NULL); - if(ret == -1 && errno != EINTR) { - err(1, "select"); - } else if(ret > 0) { - if(FD_ISSET(slipfd, &rset)) { - serial_to_tun(inslip, tunfd); - } - - if(FD_ISSET(slipfd, &wset)) { - slip_flushbuf(slipfd); - sigalarm_reset(); - } - - if(slip_empty() && FD_ISSET(tunfd, &rset)) { - tun_to_serial(tunfd, slipfd); - slip_flushbuf(slipfd); - sigalarm_reset(); - } - - if(dhsock != -1 && slip_empty() && FD_ISSET(dhsock, &rset)) { - relay_dhcp_to_client(slipfd); - slip_flushbuf(slipfd); - } - } - } -} diff --git a/tools/tunslip6.c b/tools/tunslip6.c index 49019a66b8bc7c9e8aab464cf2fded8b4d6b2a37..e1a72078a61e06df3e011d72e4cf7cbaa261e4cf 100644 --- a/tools/tunslip6.c +++ b/tools/tunslip6.c @@ -40,6 +40,7 @@ #include <stdarg.h> #include <string.h> #include <time.h> +#include <sys/time.h> #include <sys/types.h> #include <unistd.h> @@ -683,7 +684,7 @@ ifconf(const char *tundev, const char *ipaddr) } ai=0; cc=scc=0; - while(c=*ptr++) { + while((c=*ptr++) != 0) { if(c=='/') break; if(c==':') { if(cc) @@ -1025,9 +1026,8 @@ exit(1); if(dmsec>delaymsec) delaymsec=0; } if(delaymsec==0) { - int size; if(slip_empty() && FD_ISSET(tunfd, &rset)) { - size=tun_to_serial(tunfd, slipfd); + tun_to_serial(tunfd, slipfd); slip_flushbuf(slipfd); if(ipa_enable) sigalarm_reset(); if(basedelay) { diff --git a/tools/vagrant/.gitignore b/tools/vagrant/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..8000dd9db47c0b9dd34046ec17880dcbb27e5eb9 --- /dev/null +++ b/tools/vagrant/.gitignore @@ -0,0 +1 @@ +.vagrant diff --git a/tools/vagrant/README.md b/tools/vagrant/README.md new file mode 100644 index 0000000000000000000000000000000000000000..e64a0314e6e80f15c56857f7f00ecf83ad9dbc79 --- /dev/null +++ b/tools/vagrant/README.md @@ -0,0 +1 @@ +Instructions can be fonud at https://github.com/contiki-ng/contiki-ng/wiki/Vagrant diff --git a/tools/vagrant/Vagrantfile b/tools/vagrant/Vagrantfile new file mode 100644 index 0000000000000000000000000000000000000000..a4e66ab2189b5c21a9a64b9d9831b67a540bfa76 --- /dev/null +++ b/tools/vagrant/Vagrantfile @@ -0,0 +1,48 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# All Vagrant configuration is done below. The "2" in Vagrant.configure +# configures the configuration version (we support older styles for +# backwards compatibility). Please don't change it unless you know what +# you're doing. +Vagrant.configure("2") do |config| + # The most common configuration options are documented and commented below. + # For a complete reference, please see the online documentation at + # https://docs.vagrantup.com. + + # Every Vagrant development environment requires a box. You can search for + # boxes at https://vagrantcloud.com/search. + config.vm.box = "ubuntu/xenial64" + + # Disable automatic box update checking. If you disable this, then + # boxes will only be checked for updates when the user runs + # `vagrant box outdated`. This is not recommended. + # config.vm.box_check_update = false + + # Create a forwarded port mapping which allows access to a specific port + # within the machine from a port on the host machine. In the example below, + # accessing "localhost:8080" will access port 80 on the guest machine. + # NOTE: This will enable public access to the opened port + # config.vm.network "forwarded_port", guest: 80, host: 8080 + + # Share an additional folder to the guest VM. The first argument is + # the path on the host to the actual folder. The second argument is + # the path on the guest to mount the folder. And the optional third + # argument is a set of non-required options. + config.vm.synced_folder "../../", "/home/vagrant/contiki-ng" + + # Provider-specific configuration so you can fine-tune various + # backing providers for Vagrant. These expose provider-specific options. + # Example for VirtualBox: + # + # config.vm.provider "virtualbox" do |vb| + # # Display the VirtualBox GUI when booting the machine + # vb.gui = true + # + # # Customize the amount of memory on the VM: + # vb.memory = "1024" + # end + # + # View the documentation for the provider you are using for more + # information on available options. +end diff --git a/tools/vagrant/bootstrap.sh b/tools/vagrant/bootstrap.sh new file mode 100755 index 0000000000000000000000000000000000000000..996ffb12eb40c5d2b398cd5afff2d69f7626e0d0 --- /dev/null +++ b/tools/vagrant/bootstrap.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash + +# i386 binary support on x64 system +sudo dpkg --add-architecture i386 +sudo apt update +sudo apt install -y --no-install-recommends \ + libc6:i386 libstdc++6:i386 libncurses5:i386 libz1:i386 + +# Tools +sudo apt-get install -y --no-install-recommends \ + build-essential doxygen git wget unzip python-serial \ + default-jdk ant srecord python-pip iputils-tracepath uncrustify python-magic +sudo apt-get clean +sudo python2 -m pip install intelhex + +# Install ARM toolchain +wget https://launchpad.net/gcc-arm-embedded/5.0/5-2015-q4-major/+download/gcc-arm-none-eabi-5_2-2015q4-20151219-linux.tar.bz2 +tar xjf gcc-arm-none-eabi-5_2-2015q4-20151219-linux.tar.bz2 -C /tmp/ +sudo cp -f -r /tmp/gcc-arm-none-eabi-5_2-2015q4/* /usr/local/ +rm -rf /tmp/gcc-arm-none-eabi-* gcc-arm-none-eabi-*-linux.tar.bz2 + +# Install msp430 toolchain +wget http://simonduq.github.io/resources/mspgcc-4.7.2-compiled.tar.bz2 +tar xjf mspgcc*.tar.bz2 -C /tmp/ +sudo cp -f -r /tmp/msp430/* /usr/local/ +rm -rf /tmp/msp430 mspgcc*.tar.bz2 + +# Install NXP toolchain (partial, with binaries excluded. Download from nxp.com) +wget http://simonduq.github.io/resources/ba-elf-gcc-4.7.4-part1.tar.bz2 +wget http://simonduq.github.io/resources/ba-elf-gcc-4.7.4-part2.tar.bz2 +wget http://simonduq.github.io/resources/jn516x-sdk-4163-1416.tar.bz2 +mkdir -p /tmp/jn516x-sdk /tmp/ba-elf-gcc +tar xjf jn516x-sdk-*.tar.bz2 -C /tmp/jn516x-sdk +tar xjf ba-elf-gcc-*part1.tar.bz2 -C /tmp/ba-elf-gcc +tar xjf ba-elf-gcc-*part2.tar.bz2 -C /tmp/ba-elf-gcc +sudo cp -f -r /tmp/jn516x-sdk /usr/ +sudo cp -f -r /tmp/ba-elf-gcc /usr/ +rm -rf jn516x*.bz2 ba-elf-gcc*.bz2 /tmp/ba-elf-gcc* /tmp/jn516x-sdk* + +echo 'export PATH="/usr/ba-elf-gcc/bin:${PATH}"' >> ${HOME}/.bashrc + +## Install nRF52 SDK +wget https://developer.nordicsemi.com/nRF5_IoT_SDK/nRF5_IoT_SDK_v0.9.x/nrf5_iot_sdk_3288530.zip +sudo mkdir -p /usr/nrf52-sdk +sudo unzip nrf5_iot_sdk_3288530.zip -d /usr/nrf52-sdk +rm nrf5_iot_sdk_3288530.zip + +echo "export NRF52_SDK_ROOT=/usr/nrf52-sdk" >> ${HOME}/.bashrc + +sudo usermod -aG dialout vagrant + +# Environment variables +echo "export JAVA_HOME=/usr/lib/jvm/default-java" >> ${HOME}/.bashrc +echo "export CONTIKI_NG=${HOME}/contiki-ng" >> ${HOME}/.bashrc +echo "export COOJA=${CONTIKI_NG}/tools/cooja" >> ${HOME}/.bashrc +echo "export PATH=${HOME}:${PATH}" >> ${HOME}/.bashrc +echo "export WORKDIR=${HOME}" >> ${HOME}/.bashrc +source ${HOME}/.bashrc + +# Create Cooja shortcut +echo "#!/bin/bash\nant -Dbasedir=${COOJA} -f ${COOJA}/build.xml run" > ${HOME}/cooja && chmod +x ${HOME}/cooja + +# Install coap-cli +sudo apt-get install -y npm +sudo apt-get clean +sudo npm install coap-cli -g +sudo ln -s /usr/bin/nodejs /usr/bin/node + +# Docker +curl -fsSL get.docker.com -o get-docker.sh +sudo sh get-docker.sh +sudo usermod -aG docker vagrant + +# Docker image "Contiker" alias +echo 'alias contiker="docker run --privileged --mount type=bind,source=$CONTIKI_NG,destination=/home/user/contiki-ng -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix -v /dev/bus/usb:/dev/bus/usb -ti simonduq/contiki-ng"' >> /home/vagrant/.bashrc +source ${HOME}/.bashrc diff --git a/tools/viewconf.c b/tools/viewconf.c index f742b66a084c52cbb9b965be88199ba3a1b72e25..5e6ee3d5e2ae7bd737317e51cf310953d9f01ecf 100644 --- a/tools/viewconf.c +++ b/tools/viewconf.c @@ -1,8 +1,6 @@ #include "contiki.h" #include "os/net/mac/framer/frame802154.h" #include "os/net/mac/tsch/tsch.h" -#include "os/net/mac/tsch/tsch-conf.h" -#include "os/net/mac/tsch/tsch-schedule.h" #include "os/net/ipv6/uip-nd6.h" #include "os/net/ipv6/uipopt.h" #include "os/net/queuebuf.h" @@ -62,10 +60,10 @@ ##### "TSCH_CONF_DEFAULT_TIMESLOT_LENGTH": _____ -> TSCH_DEFAULT_TIMESLOT_LENGTH #endif -#ifdef TSCH_CONF_SCHEDULE_DEFAULT_LENGTH -##### "TSCH_CONF_SCHEDULE_DEFAULT_LENGTH": _____ == TSCH_CONF_SCHEDULE_DEFAULT_LENGTH +#ifdef TSCH_SCHEDULE_CONF_DEFAULT_LENGTH +##### "TSCH_SCHEDULE_CONF_DEFAULT_LENGTH": _____ == TSCH_SCHEDULE_CONF_DEFAULT_LENGTH #else -##### "TSCH_CONF_SCHEDULE_DEFAULT_LENGTH": _____ -> TSCH_CHEDULE_DEFAULT_LENGTH +##### "TSCH_SCHEDULE_CONF_DEFAULT_LENGTH": _____ -> TSCH_SCHEDULE_DEFAULT_LENGTH #endif #else /* MAC_CONF_WITH_TSCH */ @@ -150,4 +148,6 @@ ##### "LOG_CONF_LEVEL_MAC": ____________________ == LOG_CONF_LEVEL_MAC ##### "LOG_CONF_LEVEL_FRAMER": _________________ == LOG_CONF_LEVEL_FRAMER ##### "LOG_CONF_LEVEL_6TOP": ___________________ == LOG_CONF_LEVEL_6TOP +##### "LOG_CONF_LEVEL_COAP": ___________________ == LOG_CONF_LEVEL_COAP +##### "LOG_CONF_LEVEL_LWM2M": __________________ == LOG_CONF_LEVEL_LWM2M ##### "LOG_CONF_LEVEL_MAIN": ___________________ == LOG_CONF_LEVEL_MAIN diff --git a/tools/wpcapslip/contiki-conf.h b/tools/wpcapslip/contiki-conf.h index 020cbdfecd5f47ef5af7676837ba838395ad8c75..7221f403351a151250285887bc49b613f2dbaff6 100644 --- a/tools/wpcapslip/contiki-conf.h +++ b/tools/wpcapslip/contiki-conf.h @@ -1,8 +1,6 @@ #ifndef CONTIKI_CONF_H_ #define CONTIKI_CONF_H_ #include <stdint.h> -#define CCIF -#define CLIF /* These names are deprecated, use C99 names. */ typedef uint8_t u8_t;