diff --git a/.gitignore b/.gitignore index 74bef3888..f8f72f54b 100644 --- a/.gitignore +++ b/.gitignore @@ -20,8 +20,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 diff --git a/.gitmodules b/.gitmodules index f2cd29451..36eb3cd95 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 7591dd772..00dba89ab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ before_install: - 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 -c "make -C tests/??-$TEST_NAME"; + - 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 $?; @@ -26,6 +26,7 @@ env: - 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' diff --git a/LICENSE.md b/LICENSE.md index c180b146d..b2f909d44 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 3b8c41605..a37c5ad6a 100644 --- a/Makefile.include +++ b/Makefile.include @@ -8,7 +8,7 @@ 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 ifeq ($(DEFINES),) -include Makefile.$(TARGET).defines @@ -40,9 +40,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 +54,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 +87,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 +143,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 +182,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 +190,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,6 +256,7 @@ SOURCEDIRS = . $(PROJECTDIRS) $(CONTIKI_TARGET_DIRS_CONCAT) $(CONTIKI_ARCH_DIRS) vpath %.c $(SOURCEDIRS) vpath %.S $(SOURCEDIRS) +vpath %.s $(SOURCEDIRS) CFLAGS += ${addprefix -I,$(SOURCEDIRS) $(CONTIKI)} @@ -239,9 +290,8 @@ endef clean: -rm -f *~ *core core *.srec \ - *.lst *.map \ + *.lst *.map *.o \ *.cprg *.bin *.data contiki*.a *.firmware core-labels.S *.ihex *.ini \ - *.ce *.co rm -rf $(CLEAN) -rm -rf $(OBJECTDIR) @@ -250,13 +300,6 @@ distclean: clean -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 +311,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,12 +346,6 @@ 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 @@ -321,7 +361,7 @@ ifndef LD endif ifndef CUSTOM_RULE_LINK -%.$(TARGET): %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a +%.$(TARGET): %.o $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(TRACE_LD) $(Q)$(LD) $(LDFLAGS) $(TARGET_STARTFILES) ${filter-out %.a,$^} \ ${filter %.a,$^} $(TARGET_LIBFILES) -o $@ @@ -366,6 +406,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 +427,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 86dadeb75..f29f369c1 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 [![Build Status](https://travis-ci.org/contiki-ng/contiki-ng.svg?branch=master)](https://travis-ci.org/contiki-ng/contiki-ng/branches) +[![License](https://img.shields.io/badge/License-3--Clause%20BSD-brightgreen.svg)](https://github.com/contiki-ng/contiki-ng/blob/master/LICENSE.md) +[![Latest release](https://img.shields.io/github/release/contiki-ng/contiki-ng.svg)](https://github.com/contiki-ng/contiki-ng/releases/latest) +[![GitHub Release Date](https://img.shields.io/github/release-date/contiki-ng/contiki-ng.svg)](https://github.com/contiki-ng/contiki-ng/releases/latest) +[![Last commit](https://img.shields.io/github/last-commit/contiki-ng/contiki-ng.svg)](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/arm-def.h b/arch/cpu/arm/arm-def.h index 63a70a535..2cd31604c 100644 --- a/arch/cpu/arm/arm-def.h +++ b/arch/cpu/arm/arm-def.h @@ -42,16 +42,6 @@ /*---------------------------------------------------------------------------*/ #include /*---------------------------------------------------------------------------*/ -/** - * \name Compiler configuration - * - * Those values are not meant to be modified by the user - * @{ - */ -#define CCIF -#define CLIF -/** @} */ -/*---------------------------------------------------------------------------*/ /** * \name Macros and typedefs * diff --git a/arch/cpu/arm/common/usb/Makefile.usb b/arch/cpu/arm/common/usb/Makefile.usb index 3286ca365..05266cf7b 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 4e9902297..696f2e455 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 f54184395..6c89f3c03 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/cortex-m/cm3/Makefile.cm3 b/arch/cpu/arm/cortex-m/cm3/Makefile.cm3 index a422d3080..f5547fea0 100644 --- a/arch/cpu/arm/cortex-m/cm3/Makefile.cm3 +++ b/arch/cpu/arm/cortex-m/cm3/Makefile.cm3 @@ -19,7 +19,7 @@ CUSTOM_RULE_LINK = 1 .SECONDEXPANSION: -%.elf: $(CPU_STARTFILES) $$(CONTIKI_OBJECTFILES) %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) $(LDSCRIPT) +%.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 $@ diff --git a/arch/cpu/arm/cortex-m/cm4/Makefile.cm4 b/arch/cpu/arm/cortex-m/cm4/Makefile.cm4 index ca79428f1..78367b0eb 100644 --- a/arch/cpu/arm/cortex-m/cm4/Makefile.cm4 +++ b/arch/cpu/arm/cortex-m/cm4/Makefile.cm4 @@ -6,8 +6,8 @@ LDFLAGS += -mcpu=cortex-m4 ### Compilation rules CUSTOM_RULE_LINK=1 -%.elf: $(TARGET_STARTFILES) %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(TARGET_LIBS) +%.elf: $(TARGET_STARTFILES) %.o $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(TARGET_LIBS) $(TRACE_LD) - $(Q)$(CC) $(LDFLAGS) ${filter %o %.co %.a,$^} -o $@ + $(Q)$(CC) $(LDFLAGS) ${filter %.o %.a,$^} -o $@ include $(CONTIKI)/arch/cpu/arm/cortex-m/Makefile.cortex-m diff --git a/arch/cpu/cc2538/Makefile.cc2538 b/arch/cpu/cc2538/Makefile.cc2538 index c0a2bb2f0..f6e76f571 100644 --- a/arch/cpu/cc2538/Makefile.cc2538 +++ b/arch/cpu/cc2538/Makefile.cc2538 @@ -17,7 +17,7 @@ CONTIKI_CPU_DIRS = . dev usb usb/common usb/common/cdc-acm 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 += 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 int-master.c CONTIKI_CPU_SOURCEFILES += pka.c bignum-driver.c ecc-driver.c ecc-algorithm.c diff --git a/arch/cpu/cc2538/cc2538-def.h b/arch/cpu/cc2538/cc2538-def.h index 39dd18c13..32aed6111 100644 --- a/arch/cpu/cc2538/cc2538-def.h +++ b/arch/cpu/cc2538/cc2538-def.h @@ -64,6 +64,8 @@ /* 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/clock.c b/arch/cpu/cc2538/clock.c index 2842a3be8..839c72242 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/dev/gpio-hal-arch.c b/arch/cpu/cc2538/dev/gpio-hal-arch.c new file mode 100644 index 000000000..bd2dfb92d --- /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 +/*---------------------------------------------------------------------------*/ +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 000000000..0b282c738 --- /dev/null +++ b/arch/cpu/cc2538/dev/gpio-hal-arch.h @@ -0,0 +1,90 @@ +/* + * 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 +/*---------------------------------------------------------------------------*/ +#define PIN_TO_PORT(pin) (pin >> 3) +#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 a09ca6dc3..c5c72594b 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 - -/** - * \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 00ee1b1dc..67b28cf0d 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 - -/** - * \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 53a9218a9..5bb631c46 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 7fad9d275..ae14a616f 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/soc.c b/arch/cpu/cc2538/soc.c index e0ab1a918..1aa910095 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/usb/cdc-acm-descriptors.c b/arch/cpu/cc2538/usb/cdc-acm-descriptors.c index eb2a9d7b3..fd56ed303 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 f54184395..6c89f3c03 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 9a2899ea7..979d7f5e4 100644 --- a/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx +++ b/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx @@ -25,15 +25,16 @@ ifdef NODEID endif ### CPU-dependent directories -CONTIKI_CPU_DIRS += . dev rf-core rf-core/api $(TI_XXWARE_STARTUP_DIR) +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 += 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 += 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 DEBUG_IO_SOURCEFILES += dbg-printf.c dbg-snprintf.c dbg-sprintf.c strformat.c diff --git a/arch/cpu/cc26xx-cc13xx/ble-addr.c b/arch/cpu/cc26xx-cc13xx/ble-addr.c new file mode 100644 index 000000000..7617133cc --- /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 + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "net/linkaddr.h" +#include + +#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 000000000..4f61b0dd6 --- /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 + */ +/*---------------------------------------------------------------------------*/ +#ifndef BLE_ADDR_H_ +#define BLE_ADDR_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include +/*---------------------------------------------------------------------------*/ +/* 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/cc13xx-cc26xx-conf.h b/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-conf.h index 6ecdafa6b..83519f795 100644 --- a/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-conf.h +++ b/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-conf.h @@ -90,7 +90,9 @@ #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 */ diff --git a/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-def.h b/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-def.h index e8720b5f4..7b914ac1e 100644 --- a/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-def.h +++ b/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-def.h @@ -99,6 +99,10 @@ /* 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 /*---------------------------------------------------------------------------*/ #endif /* CC13XX_CC26XX_DEF_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/cc26xx-cc13xx/clock.c b/arch/cpu/cc26xx-cc13xx/clock.c index 981bbb4b2..172d1c3fd 100644 --- a/arch/cpu/cc26xx-cc13xx/clock.c +++ b/arch/cpu/cc26xx-cc13xx/clock.c @@ -124,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(); @@ -142,7 +142,7 @@ clock_update(void) } } /*---------------------------------------------------------------------------*/ -CCIF unsigned long +unsigned long clock_seconds(void) { bool interrupts_disabled; diff --git a/arch/cpu/cc26xx-cc13xx/dev/adc-sensor.c b/arch/cpu/cc26xx-cc13xx/dev/adc-sensor.c index 1f736bb53..c88b2e5fe 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 014e9a17d..cde7abc8e 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 000000000..a7b025800 --- /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 +/*---------------------------------------------------------------------------*/ +#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 000000000..7d87670c5 --- /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 +/*---------------------------------------------------------------------------*/ +#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 348d0646a..c90e9239d 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 /*---------------------------------------------------------------------------*/ #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/rf-core/ble-cc2650.c b/arch/cpu/cc26xx-cc13xx/rf-core/ble-cc2650.c new file mode 100644 index 000000000..6510ac50e --- /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 + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/radio.h" +#include "os/dev/ble-hal.h" +#include "rf-core/ble-hal/ble-hal-cc26xx.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +#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 000000000..d4c761dcd --- /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 + */ +/*---------------------------------------------------------------------------*/ + +#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 + +#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 000000000..41e71c684 --- /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 + */ +/*---------------------------------------------------------------------------*/ + +#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 000000000..cde42f99b --- /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 + */ +/*---------------------------------------------------------------------------*/ +#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 000000000..d8a86f798 --- /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 + */ +/*---------------------------------------------------------------------------*/ + +#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 cf1676570..a5479a4ee 100644 --- a/arch/cpu/cc26xx-cc13xx/rf-core/ieee-mode.c +++ b/arch/cpu/cc26xx-cc13xx/rf-core/ieee-mode.c @@ -263,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 }; @@ -565,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 @@ -601,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; @@ -1079,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"); @@ -1095,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); diff --git a/arch/cpu/msp430/Makefile.msp430 b/arch/cpu/msp430/Makefile.msp430 index f7267b694..ec8c33664 100644 --- a/arch/cpu/msp430/Makefile.msp430 +++ b/arch/cpu/msp430/Makefile.msp430 @@ -108,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 @@ -195,10 +190,6 @@ PROJECT_OBJECTFILES += ${addprefix $(OBJECTDIR)/,$(CONTIKI_TARGET_MAIN:.c=.o)} $(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 $@ $< @@ -206,7 +197,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-$(TARGET).a $(LD) $(LDFLAGSNO) -Fintel-extended $(TARGET_STARTFILES) ${filter-out %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -o $@ else %.ihex: %.$(TARGET) diff --git a/arch/cpu/msp430/dev/uart0-putchar.c b/arch/cpu/msp430/dev/uart0-putchar.c index bf237695b..4c92f9160 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 +/*---------------------------------------------------------------------------*/ +#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 7623b435a..14146d9dc 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 +/*---------------------------------------------------------------------------*/ +#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/leds-arch.c b/arch/cpu/msp430/leds-arch.c index fe63d8ae4..c8131ee3e 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/msp430/msp430-conf.h b/arch/cpu/msp430/msp430-conf.h index ec4f49a55..f4f0da54c 100644 --- a/arch/cpu/msp430/msp430-conf.h +++ b/arch/cpu/msp430/msp430-conf.h @@ -1,30 +1,30 @@ /* * 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 MSP430_CONF_H_ @@ -42,6 +42,20 @@ #else #define MSP430_CPU_SPEED 2457600UL #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 +#else +#define SLIP_ARCH_CONF_ENABLED 0 +#endif +#endif + /*---------------------------------------------------------------------------*/ #endif /* MSP430_CONF_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/arch/cpu/msp430/msp430-def.h b/arch/cpu/msp430/msp430-def.h index 2f14d7236..93e575702 100644 --- a/arch/cpu/msp430/msp430-def.h +++ b/arch/cpu/msp430/msp430-def.h @@ -79,9 +79,6 @@ typedef long off_t; /* Our clock resolution, this is the same as Unix HZ. */ #define CLOCK_CONF_SECOND 128UL -#define CCIF -#define CLIF - typedef int spl_t; spl_t splhigh_(void); diff --git a/arch/cpu/nrf52832/Makefile.nrf52832 b/arch/cpu/nrf52832/Makefile.nrf52832 index 567270834..c2bdbbf81 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),) @@ -145,7 +139,7 @@ CFLAGS += -ggdb CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 # keep every function in separate section. This will allow linker to dump unused functions -LDFLAGS += -Xlinker -Map=$(LISTING_DIRECTORY)/$(OUTPUT_FILENAME).map +LDFLAGS += -Xlinker -Map=$(@:.elf=-$(TARGET).map) LDFLAGS += -mabi=aapcs -L $(TEMPLATE_PATH) -T$(LINKER_SCRIPT) LDFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 # let linker to dump unused sections diff --git a/arch/cpu/nrf52832/dev/clock.c b/arch/cpu/nrf52832/dev/clock.c index 68413c23b..496668ecb 100644 --- a/arch/cpu/nrf52832/dev/clock.c +++ b/arch/cpu/nrf52832/dev/clock.c @@ -116,7 +116,7 @@ clock_init(void) rtc_config(); } /*---------------------------------------------------------------------------*/ -CCIF clock_time_t +clock_time_t clock_time(void) { return (clock_time_t)(ticks & 0xFFFFFFFF); @@ -131,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/nrf52832-def.h b/arch/cpu/nrf52832/nrf52832-def.h index f31054dda..b5eca1b5e 100644 --- a/arch/cpu/nrf52832/nrf52832-def.h +++ b/arch/cpu/nrf52832/nrf52832-def.h @@ -34,6 +34,11 @@ /*---------------------------------------------------------------------------*/ #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/dev/rgb-led/rgb-led.c b/arch/dev/rgb-led/rgb-led.c new file mode 100644 index 000000000..521583022 --- /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 000000000..d0cd81d38 --- /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 +/*---------------------------------------------------------------------------*/ +#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 a9870079f..2b88479d2 100644 --- a/arch/platform/cc2538dk/Makefile.cc2538dk +++ b/arch/platform/cc2538dk/Makefile.cc2538dk @@ -6,10 +6,10 @@ 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) @@ -19,8 +19,7 @@ CLEAN += *.cc2538dk 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 1a463a0be..649fde347 100644 --- a/arch/platform/cc2538dk/contiki-conf.h +++ b/arch/platform/cc2538dk/contiki-conf.h @@ -41,6 +41,7 @@ #include #include +#include /*---------------------------------------------------------------------------*/ /* Include Project Specific conf */ #ifdef PROJECT_CONF_PATH diff --git a/arch/platform/cc2538dk/dev/board-buttons.c b/arch/platform/cc2538dk/dev/board-buttons.c new file mode 100644 index 000000000..6afc915df --- /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 6e3021ceb..80f036fd7 100644 --- a/arch/platform/cc2538dk/dev/board.h +++ b/arch/platform/cc2538dk/dev/board.h @@ -71,20 +71,25 @@ * @{ */ /*---------------------------------------------------------------------------*/ -#define LEDS_YELLOW 2 /**< LED2 (Yellow) -> PC1 */ -#define LEDS_GREEN 4 /**< LED3 (Green) -> PC2 */ -#define LEDS_ORANGE 8 /**< LED4 (Orange) -> PC3 */ +#define LEDS_CONF_YELLOW 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_ORANGE 4 + +#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 @@ -158,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 14d4e7d15..000000000 --- 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 -#include - -#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 266770d24..000000000 --- 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 661f46160..c849355b4 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,34 @@ * 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 +#include /*---------------------------------------------------------------------------*/ -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); -} -/*---------------------------------------------------------------------------*/ -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 76841af3b..1b833e764 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 /** \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 3897c6292..bf945bfdd 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; @@ -121,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,6 +158,8 @@ platform_init_stage_two() /* Populate linkaddr_node_addr */ ieee_addr_cpy_to(linkaddr_node_addr.u8, LINKADDR_SIZE); + button_hal_init(); + INTERRUPTS_ENABLE(); fade(LEDS_GREEN); diff --git a/arch/platform/cooja/Makefile.cooja b/arch/platform/cooja/Makefile.cooja index 9f41dbaad..541ae51f0 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) diff --git a/arch/platform/cooja/Makefile.customrules-cooja b/arch/platform/cooja/Makefile.customrules-cooja index de35d4185..42d6e125e 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 af7582ab9..75a37f866 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 @@ -98,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 typedef uint8_t u8_t; diff --git a/arch/platform/cooja/dev/leds-arch.c b/arch/platform/cooja/dev/leds-arch.c index db91e9baa..b65df2945 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/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 39793d12c..9ef310bce 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() { - /* 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); - } else { - printf("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]); +} +/*---------------------------------------------------------------------------*/ +void +platform_init_stage_three() +{ + if(node_id > 0) { + LOG_INFO("Node id is set to %u.\n", node_id); + } else { + LOG_INFO("Node id is not set.\n"); } - - /* 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(); + /* Yield once during bootup */ + simProcessRunValue = 1; + cooja_mt_yield(); - contiki_init(); - - 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/jn516x/Makefile.jn516x b/arch/platform/jn516x/Makefile.jn516x index bb654ceb8..ecdcc2f58 100644 --- a/arch/platform/jn516x/Makefile.jn516x +++ b/arch/platform/jn516x/Makefile.jn516x @@ -143,8 +143,6 @@ 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) @@ -236,7 +234,7 @@ 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-$(TARGET).a $(ABS_APPLIBS) echo ${filter %.a,$^} $(Q)$(CC) -Wl,--gc-sections $(LDFLAGS) -T$(LINKCMD) -o $@ -Wl,--start-group \ $(patsubst /cygdrive/c/%,c:/%,${filter-out %.a,$^}) \ @@ -245,7 +243,7 @@ ifneq ($(wildcard $(SDK_BASE_DIR)/Components/Library/*),) $(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-$(TARGET).a echo Creating empty $@ touch $@ endif diff --git a/arch/platform/jn516x/dev/dongle/leds-arch.c b/arch/platform/jn516x/dev/dongle/leds-arch.c index 5eff3c63e..513d52b76 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/micromac-radio.c b/arch/platform/jn516x/dev/micromac-radio.c index c3117c6f8..3ebc13578 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/jn516x-def.h b/arch/platform/jn516x/jn516x-def.h index 357c255c0..596d55333 100644 --- a/arch/platform/jn516x/jn516x-def.h +++ b/arch/platform/jn516x/jn516x-def.h @@ -196,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 @@ -217,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 #else @@ -272,9 +271,14 @@ typedef uint32_t clock_time_t; /* Set this to zero only if we are using SLIP */ #ifndef SLIP_BRIDGE_CONF_NO_PUTCHAR -#define SLIP_BRIDGE_CONF_NO_PUTCHAR 1 +#if defined(UIP_FALLBACK_INTERFACE) || defined(CMD_CONF_OUTPUT) +#define SLIP_BRIDGE_CONF_NO_PUTCHAR 0 +#else +#define SLIP_BRIDGE_CONF_NO_PUTCHAR 1 +#endif #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 diff --git a/arch/platform/native/Makefile.native b/arch/platform/native/Makefile.native index 2d1ee4fbc..bee104a6c 100644 --- a/arch/platform/native/Makefile.native +++ b/arch/platform/native/Makefile.native @@ -30,8 +30,8 @@ CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) # Enable nullmac by default MAKE_MAC ?= MAKE_MAC_NULLMAC +CLEAN += *.native + ### 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/contiki-conf.h b/arch/platform/native/contiki-conf.h index c315b8e18..b8a43a604 100644 --- a/arch/platform/native/contiki-conf.h +++ b/arch/platform/native/contiki-conf.h @@ -58,18 +58,19 @@ 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; +#define LEDS_CONF_LEGACY_API 1 + +#ifndef UIP_CONF_BYTE_ORDER #define UIP_CONF_BYTE_ORDER UIP_LITTLE_ENDIAN +#endif #if NETSTACK_CONF_WITH_IPV6 diff --git a/arch/platform/native/dev/leds-arch.c b/arch/platform/native/dev/leds-arch.c index 1308c57dc..07addc84e 100644 --- a/arch/platform/native/dev/leds-arch.c +++ b/arch/platform/native/dev/leds-arch.c @@ -38,7 +38,7 @@ */ #include "dev/leds.h" -static unsigned char leds; +static leds_mask_t leds; /*---------------------------------------------------------------------------*/ void leds_arch_init(void) @@ -46,14 +46,14 @@ leds_arch_init(void) leds = 0; } /*---------------------------------------------------------------------------*/ -unsigned char +leds_mask_t leds_arch_get(void) { return leds; } /*---------------------------------------------------------------------------*/ void -leds_arch_set(unsigned char l) +leds_arch_set(leds_mask_t l) { leds = l; } diff --git a/arch/platform/native/platform.c b/arch/platform/native/platform.c index 02fad921c..fceab0207 100644 --- a/arch/platform/native/platform.c +++ b/arch/platform/native/platform.c @@ -70,16 +70,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; -static uint8_t serial_id[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}; +#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 */ + #if !NETSTACK_CONF_WITH_IPV6 static uint16_t node_id = 0x0102; #endif /* !NETSTACK_CONF_WITH_IPV6 */ @@ -116,6 +153,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) { @@ -135,6 +173,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) @@ -143,12 +182,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; @@ -219,6 +258,7 @@ void platform_init_stage_two() { set_lladdr(); + serial_line_init(); } /*---------------------------------------------------------------------------*/ void @@ -240,7 +280,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; @@ -252,7 +294,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 9c3778a73..6187fc532 100644 --- a/arch/platform/nrf52dk/Makefile.nrf52dk +++ b/arch/platform/nrf52dk/Makefile.nrf52dk @@ -27,5 +27,3 @@ 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/contiki-conf.h b/arch/platform/nrf52dk/contiki-conf.h index f7b8b1fa1..7b3b66314 100644 --- a/arch/platform/nrf52dk/contiki-conf.h +++ b/arch/platform/nrf52dk/contiki-conf.h @@ -41,6 +41,7 @@ #define CONTIKI_CONF_H #include +#include /*---------------------------------------------------------------------------*/ /* Include Project Specific conf */ #ifdef PROJECT_CONF_PATH diff --git a/arch/platform/nrf52dk/dev/leds-arch.c b/arch/platform/nrf52dk/dev/leds-arch.c index 019589493..cda1317ef 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/nrf52dk-def.h b/arch/platform/nrf52dk/nrf52dk-def.h index ea4060ca2..0e387f0f0 100644 --- a/arch/platform/nrf52dk/nrf52dk-def.h +++ b/arch/platform/nrf52dk/nrf52dk-def.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) diff --git a/arch/platform/nrf52dk/platform.c b/arch/platform/nrf52dk/platform.c index a2ba55385..e48a3c05d 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 94174a0a1..14aa46f78 100644 --- a/arch/platform/openmote-cc2538/Makefile.openmote-cc2538 +++ b/arch/platform/openmote-cc2538/Makefile.openmote-cc2538 @@ -15,7 +15,7 @@ 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) @@ -26,8 +26,7 @@ CLEAN += *.openmote-cc2538 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 56724a753..abb89b8e2 100644 --- a/arch/platform/openmote-cc2538/board.h +++ b/arch/platform/openmote-cc2538/board.h @@ -63,14 +63,21 @@ * @{ */ /*---------------------------------------------------------------------------*/ -#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_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 -/* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define LEDS_CONF_RED 1 +#define LEDS_CONF_YELLOW 2 +#define LEDS_CONF_GREEN 4 +#define LEDS_CONF_ORANGE 8 + +#define LEDS_CONF_COUNT 4 /** @} */ /*---------------------------------------------------------------------------*/ /** \name USB configuration @@ -121,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 d9f0b047e..daa203065 100644 --- a/arch/platform/openmote-cc2538/contiki-conf.h +++ b/arch/platform/openmote-cc2538/contiki-conf.h @@ -50,6 +50,7 @@ #include #include +#include /*---------------------------------------------------------------------------*/ /* Include Project Specific conf */ #ifdef PROJECT_CONF_PATH 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 000000000..654302f24 --- /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 9c6a7d6c8..000000000 --- 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 -#include -/*---------------------------------------------------------------------------*/ -#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 28454dacf..2bc13bed8 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,32 @@ * 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" +#include "dev/gpio-hal.h" + +#include /*---------------------------------------------------------------------------*/ -#define LEDS_GPIO_PIN_MASK LEDS_ALL +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_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); -} -/*---------------------------------------------------------------------------*/ -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 3b55e4cbb..772087fa9 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 a765dbd3d..811518625 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 df1d74a47..c226785c6 100644 --- a/arch/platform/openmote-cc2538/platform.c +++ b/arch/platform/openmote-cc2538/platform.c @@ -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; @@ -157,6 +159,8 @@ platform_init_stage_two() /* Populate linkaddr_node_addr */ ieee_addr_cpy_to(linkaddr_node_addr.u8, LINKADDR_SIZE); + button_hal_init(); + INTERRUPTS_ENABLE(); fade(LEDS_BLUE); @@ -175,8 +179,6 @@ platform_init_stage_three() process_start(&sensors_process, NULL); - SENSORS_ACTIVATE(button_sensor); - fade(LEDS_GREEN); } /*---------------------------------------------------------------------------*/ diff --git a/arch/platform/sky/Makefile.sky b/arch/platform/sky/Makefile.sky index 9f86b6499..9467603a4 100644 --- a/arch/platform/sky/Makefile.sky +++ b/arch/platform/sky/Makefile.sky @@ -4,8 +4,8 @@ CONTIKI_TARGET_SOURCEFILES += contiki-sky-platform.c \ sht11.c sht11-sensor.c light-sensor.c battery-sensor.c \ button-sensor.c +CLEAN += *.sky + 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/platform.c b/arch/platform/sky/platform.c index 5bbce5286..d71471340 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; diff --git a/arch/platform/sky/sky-def.h b/arch/platform/sky/sky-def.h index 8640892af..edab43ee7 100644 --- a/arch/platform/sky/sky-def.h +++ b/arch/platform/sky/sky-def.h @@ -52,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 @@ -72,6 +75,8 @@ #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 diff --git a/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx b/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx index 393cb6286..7bead9fff 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,8 +14,7 @@ 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) @@ -30,5 +29,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 000000000..33cc5123b --- /dev/null +++ b/arch/platform/srf06-cc26xx/cfs-coffee-arch.h @@ -0,0 +1,88 @@ +/* + * 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 + */ + +#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/xmem.c b/arch/platform/srf06-cc26xx/common/xmem.c new file mode 100644 index 000000000..5a79be6c1 --- /dev/null +++ b/arch/platform/srf06-cc26xx/common/xmem.c @@ -0,0 +1,168 @@ +/* + * 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 + * + * 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 /* 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(); +} + + +int +xmem_pread(void *_p, int size, unsigned long addr) +{ + int rv; + uint8_t x; + int i; + + rv = ext_flash_open(); + + if(!rv) { + PRINTF("Could not open flash to save config\n"); + ext_flash_close(); + return -1; + } + + rv = ext_flash_read(addr, size, _p); + for (i = 0; i < size; i++){ + x = ~*((uint8_t *)_p + i); + *((uint8_t *)_p+i) = x; + } + + ext_flash_close(); + + 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(); + + if(!rv) { + PRINTF("Could not open flash to save config!\n"); + ext_flash_close(); + 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(addr + j, to_write, tmp_buf); + if (!rv) { + PRINTF("Could not write flash memory!\n"); + return size - remain; + } + } + + ext_flash_close(); + + return size; +} + + +int +xmem_erase(long size, unsigned long addr) +{ + int rv; + + rv = ext_flash_open(); + + + if(!rv) { + PRINTF("Could not open flash to save config\n"); + ext_flash_close(); + 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(addr, size); + + ext_flash_close(); + + 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 718efc3f6..4a1470b40 100644 --- a/arch/platform/srf06-cc26xx/contiki-conf.h +++ b/arch/platform/srf06-cc26xx/contiki-conf.h @@ -38,6 +38,7 @@ #define CONTIKI_CONF_H #include +#include /*---------------------------------------------------------------------------*/ /* Include Project Specific conf */ #ifdef PROJECT_CONF_PATH @@ -58,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 diff --git a/arch/platform/srf06-cc26xx/launchpad/Makefile.launchpad b/arch/platform/srf06-cc26xx/launchpad/Makefile.launchpad index 54bd81ced..f10f979da 100644 --- a/arch/platform/srf06-cc26xx/launchpad/Makefile.launchpad +++ b/arch/platform/srf06-cc26xx/launchpad/Makefile.launchpad @@ -2,7 +2,7 @@ CFLAGS += -DBOARD_LAUNCHPAD=1 CONTIKI_TARGET_DIRS += launchpad common -BOARD_SOURCEFILES += board.c launchpad-sensors.c leds-arch.c button-sensor.c +BOARD_SOURCEFILES += board.c board-buttons.c xmem.c BOARD_SOURCEFILES += ext-flash.c board-spi.c ### Signal that we can be programmed with cc2538-bsl 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 000000000..f07fff09e --- /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 3e1220234..0ad9c6b68 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 74b12bd3d..7baf71d47 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" 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 eb8bd3033..000000000 --- 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 -/*---------------------------------------------------------------------------*/ -#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 1d56d776a..7c58e1db8 100644 --- a/arch/platform/srf06-cc26xx/launchpad/cc1310/board.h +++ b/arch/platform/srf06-cc26xx/launchpad/cc1310/board.h @@ -55,20 +55,14 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -#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 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -79,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) /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -197,6 +188,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 9b5019179..63ad25374 100644 --- a/arch/platform/srf06-cc26xx/launchpad/cc1350/board.h +++ b/arch/platform/srf06-cc26xx/launchpad/cc1350/board.h @@ -55,20 +55,14 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -#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 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -79,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) /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -214,6 +205,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 65a5bb766..39b906e84 100644 --- a/arch/platform/srf06-cc26xx/launchpad/cc2650/board.h +++ b/arch/platform/srf06-cc26xx/launchpad/cc2650/board.h @@ -55,20 +55,14 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -#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 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -79,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) /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -198,6 +189,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 0d8385ad6..5d70dea40 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,17 @@ * 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); +#include +/*---------------------------------------------------------------------------*/ +const leds_t leds_arch_leds[] = { + { .pin = BOARD_IOID_LED_1, .negative_logic = false }, + { .pin = BOARD_IOID_LED_2, .negative_logic = false }, +}; +/*---------------------------------------------------------------------------*/ - ti_lib_gpio_clear_multi_dio(BOARD_LED_ALL); -} -/*---------------------------------------------------------------------------*/ -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); - } -} -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/srf06-cc26xx/platform.c b/arch/platform/srf06-cc26xx/platform.c index 7b8a8c477..bfda15dad 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 68e4b007f..46cf25a68 100644 --- a/arch/platform/srf06-cc26xx/sensortag/Makefile.sensortag +++ b/arch/platform/srf06-cc26xx/sensortag/Makefile.sensortag @@ -3,8 +3,8 @@ 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 += hdc-1000-sensor.c mpu-9250-sensor.c xmem.c +BOARD_SOURCEFILES += ext-flash.c buzzer.c BOARD_SOURCEFILES += board.c board-spi.c board-i2c.c diff --git a/arch/platform/srf06-cc26xx/sensortag/button-sensor.h b/arch/platform/srf06-cc26xx/sensortag/board-buttons.c similarity index 68% rename from arch/platform/srf06-cc26xx/sensortag/button-sensor.h rename to arch/platform/srf06-cc26xx/sensortag/board-buttons.c index 1355a5855..4a1b02ed5 100644 --- a/arch/platform/srf06-cc26xx/sensortag/button-sensor.h +++ b/arch/platform/srf06-cc26xx/sensortag/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 @@ -32,34 +33,30 @@ * \addtogroup sensortag-cc26xx-peripherals * @{ * - * \defgroup sensortag-cc26xx-button-sensor SensorTag 2.0 Button Sensor - * - * One of the buttons can be configured as general purpose or as an on/off key - * @{ - * * \file - * Header file for the Sensortag Button Driver + * Defines Sensortag buttons for use with the button HAL */ /*---------------------------------------------------------------------------*/ -#ifndef BUTTON_SENSOR_H_ -#define BUTTON_SENSOR_H_ -/*---------------------------------------------------------------------------*/ -#include "lib/sensors.h" -/*---------------------------------------------------------------------------*/ -#define BUTTON_SENSOR "Button" -/*---------------------------------------------------------------------------*/ -#define BUTTON_SENSOR_VALUE_STATE 0 -#define BUTTON_SENSOR_VALUE_DURATION 1 +#include "contiki.h" +#include "dev/gpio-hal.h" +#include "dev/button-hal.h" -#define BUTTON_SENSOR_VALUE_RELEASED 0 -#define BUTTON_SENSOR_VALUE_PRESSED 1 +#include "ti-lib.h" + +#include /*---------------------------------------------------------------------------*/ -extern const struct sensors_sensor button_left_sensor; -extern const struct sensors_sensor button_right_sensor; +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); /*---------------------------------------------------------------------------*/ -#endif /* BUTTON_SENSOR_H_ */ +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 42e22d4c8..65c03198b 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/button-sensor.c b/arch/platform/srf06-cc26xx/sensortag/button-sensor.c deleted file mode 100644 index 7ec0a5a18..000000000 --- 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 -/*---------------------------------------------------------------------------*/ -#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 3cacec197..cdae4c2b1 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 dbd64e538..aa8719eea 100644 --- a/arch/platform/srf06-cc26xx/sensortag/cc1350/board.h +++ b/arch/platform/srf06-cc26xx/sensortag/cc1350/board.h @@ -58,20 +58,13 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -#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 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -81,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 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -247,6 +238,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 f4214628e..21b8cf968 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,15 @@ * 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" +#include /*---------------------------------------------------------------------------*/ -static unsigned char c; -static int inited = 0; +const leds_t leds_arch_leds[] = { + { .pin = BOARD_IOID_LED_1, .negative_logic = false }, +}; /*---------------------------------------------------------------------------*/ -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); -} -/*---------------------------------------------------------------------------*/ -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); - } -} -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/srf06-cc26xx/sensortag/cc2650/Makefile.cc2650 b/arch/platform/srf06-cc26xx/sensortag/cc2650/Makefile.cc2650 index 5b7cdadd9..e91cabda4 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 977712ef2..9543d2713 100644 --- a/arch/platform/srf06-cc26xx/sensortag/cc2650/board.h +++ b/arch/platform/srf06-cc26xx/sensortag/cc2650/board.h @@ -58,20 +58,14 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -#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 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -82,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) /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -227,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 c36959063..cab4888b7 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,16 @@ * 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" +#include /*---------------------------------------------------------------------------*/ -static unsigned char c; -static int inited = 0; +const leds_t leds_arch_leds[] = { + { .pin = BOARD_IOID_LED_1, .negative_logic = false }, + { .pin = BOARD_IOID_LED_2, .negative_logic = false }, +}; /*---------------------------------------------------------------------------*/ -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); -} -/*---------------------------------------------------------------------------*/ -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); - } -} -/*---------------------------------------------------------------------------*/ -/** @} */ 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 736b2170a..000000000 --- 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 -/*---------------------------------------------------------------------------*/ -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 26d08591d..065ef6112 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 /*---------------------------------------------------------------------------*/ /** \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 44d115ec8..dde7e9672 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 000000000..c0db8daaa --- /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 23f668355..000000000 --- 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 -/*---------------------------------------------------------------------------*/ -#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 e210d82d8..9fece9180 100644 --- a/arch/platform/srf06-cc26xx/srf06/cc13xx/board.h +++ b/arch/platform/srf06-cc26xx/srf06/cc13xx/board.h @@ -58,20 +58,16 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -#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 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -84,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) /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -242,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 99f97fbf2..b9171388a 100644 --- a/arch/platform/srf06-cc26xx/srf06/cc26xx/board.h +++ b/arch/platform/srf06-cc26xx/srf06/cc26xx/board.h @@ -58,20 +58,16 @@ #include "ioc.h" /*---------------------------------------------------------------------------*/ /** - * \name LED configurations + * \name LED HAL configuration * * Those values are not meant to be modified by the user * @{ */ -#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 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -84,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) /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -242,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 2a1627005..fba996b39 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,18 @@ * 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; +#include "dev/gpio-hal.h" - 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); - - ti_lib_gpio_clear_multi_dio(BOARD_LED_ALL); -} +#include /*---------------------------------------------------------------------------*/ -unsigned char -leds_arch_get(void) -{ - return c; -} +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 }, +}; /*---------------------------------------------------------------------------*/ -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); - } -} -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/arch/platform/srf06-cc26xx/srf06/srf06-sensors.c b/arch/platform/srf06-cc26xx/srf06/srf06-sensors.c index 5f65a0cb2..642d2b103 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 /*---------------------------------------------------------------------------*/ /** \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 9e25275a4..6bbcd675b 100644 --- a/arch/platform/zoul/Makefile.zoul +++ b/arch/platform/zoul/Makefile.zoul @@ -31,9 +31,9 @@ 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) @@ -44,9 +44,7 @@ CLEAN += *.zoul 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 cfca8f9f1..098c37404 100644 --- a/arch/platform/zoul/contiki-conf.h +++ b/arch/platform/zoul/contiki-conf.h @@ -47,6 +47,7 @@ #include #include +#include /*---------------------------------------------------------------------------*/ /* Include Project Specific conf */ #ifdef PROJECT_CONF_PATH @@ -85,6 +86,8 @@ /*---------------------------------------------------------------------------*/ /* board.h assumes that basic configuration is done */ #include "board.h" + +#define PLATFORM_SUPPORTS_BUTTON_HAL PLATFORM_HAS_BUTTON /*---------------------------------------------------------------------------*/ /** * \name Radio Configuration diff --git a/arch/platform/zoul/dev/ac-dimmer.c b/arch/platform/zoul/dev/ac-dimmer.c index 5c27c2ffc..e5bb9b1f4 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 0ed6dd819..93532caa4 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" /*---------------------------------------------------------------------------*/ -#include "lib/sensors.h" +#if PLATFORM_HAS_BUTTON /*---------------------------------------------------------------------------*/ -extern const struct sensors_sensor reed_relay_sensor; +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); /*---------------------------------------------------------------------------*/ -#endif /* REED_RELAY_H */ +BUTTON_HAL_BUTTONS(&button_user); +/*---------------------------------------------------------------------------*/ +#endif /*---------------------------------------------------------------------------*/ /** * @} diff --git a/arch/platform/zoul/dev/button-sensor.c b/arch/platform/zoul/dev/button-sensor.c deleted file mode 100644 index 80c7b75cb..000000000 --- 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 -#include -/*---------------------------------------------------------------------------*/ -#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 12e333c4a..000000000 --- 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 92e686a4e..1aff2ef40 100644 --- a/arch/platform/zoul/dev/cc1200-zoul-arch.c +++ b/arch/platform/zoul/dev/cc1200-zoul-arch.c @@ -52,6 +52,7 @@ #include "dev/spi.h" #include "dev/ssi.h" #include "dev/gpio.h" +#include "dev/gpio-hal.h" #include /*---------------------------------------------------------------------------*/ #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 ce316a207..1ef9d6036 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 f09ed645c..eea4187c0 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,27 @@ * 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" +#include "dev/gpio-hal.h" + +#include /*---------------------------------------------------------------------------*/ -#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); -} -/*---------------------------------------------------------------------------*/ -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/motion-sensor.c b/arch/platform/zoul/dev/motion-sensor.c index ce31c3c46..a44462d69 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 b5cb116c3..d03413d5b 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 3f6870547..ffcf2e218 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 357c37d4b..cc78f9654 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 da755fc79..8015a183e 100644 --- a/arch/platform/zoul/dev/zoul-sensors.c +++ b/arch/platform/zoul/dev/zoul-sensors.c @@ -47,12 +47,7 @@ #include /*---------------------------------------------------------------------------*/ /** \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 5682c972c..92635810a 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/firefly-reva/Makefile.firefly-reva b/arch/platform/zoul/firefly-reva/Makefile.firefly-reva index 50cb71997..afecf9fa5 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 bea1fc746..784f9e902 100644 --- a/arch/platform/zoul/firefly-reva/board.h +++ b/arch/platform/zoul/firefly-reva/board.h @@ -98,20 +98,18 @@ * @{ */ /*---------------------------------------------------------------------------*/ -/* 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_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 -#define LEDS_CONF_ALL (LEDS_GREEN | LEDS_BLUE | LEDS_RED) +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_BLUE 4 -#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 50cb71997..afecf9fa5 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 4a58fc0cc..0367ea8df 100644 --- a/arch/platform/zoul/firefly/board.h +++ b/arch/platform/zoul/firefly/board.h @@ -98,20 +98,18 @@ * @{ */ /*---------------------------------------------------------------------------*/ -/* 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_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 -#define LEDS_CONF_ALL (LEDS_GREEN | LEDS_BLUE | LEDS_RED) +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_BLUE 4 -#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 7c5804d39..ebc1bdad4 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 494d79372..ee80cc709 100644 --- a/arch/platform/zoul/orion/board.h +++ b/arch/platform/zoul/orion/board.h @@ -67,20 +67,18 @@ * @{ */ /*---------------------------------------------------------------------------*/ -/* 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_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 -#define LEDS_CONF_ALL (LEDS_GREEN | LEDS_BLUE | LEDS_RED) +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_BLUE 4 -#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/platform.c b/arch/platform/zoul/platform.c index f71c9e46a..8cce149ee 100644 --- a/arch/platform/zoul/platform.c +++ b/arch/platform/zoul/platform.c @@ -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 #include #include +#include /*---------------------------------------------------------------------------*/ /* 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; @@ -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 @@ -220,6 +223,10 @@ platform_init_stage_two() /* Populate linkaddr_node_addr */ ieee_addr_cpy_to(linkaddr_node_addr.u8, LINKADDR_SIZE); +#if PLATFORM_HAS_BUTTON + button_hal_init(); +#endif + INTERRUPTS_ENABLE(); fade(LEDS_BLUE); @@ -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 6b4a80e75..fcccdf0f4 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 70a8ffdab..23722badd 100644 --- a/arch/platform/zoul/remote-reva/board.h +++ b/arch/platform/zoul/remote-reva/board.h @@ -102,20 +102,18 @@ * @{ */ /*---------------------------------------------------------------------------*/ -/* 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_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 -#define LEDS_CONF_ALL (LEDS_GREEN | LEDS_BLUE | LEDS_RED) +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_BLUE 4 -#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 d23362c32..fcccdf0f4 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 432b4b062..244489562 100644 --- a/arch/platform/zoul/remote-revb/board.h +++ b/arch/platform/zoul/remote-revb/board.h @@ -105,26 +105,18 @@ * @{ */ /*---------------------------------------------------------------------------*/ -#define LEDS_RED 1 /**< LED1 (Red) -> PD4 */ -#define LEDS_RED_PIN_MASK (1 << 4) -#define LEDS_RED_PORT_BASE GPIO_D_BASE +#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_GREEN 2 /**< LED2 (Green) -> PB7 */ -#define LEDS_GREEN_PIN_MASK (1 << 7) -#define LEDS_GREEN_PORT_BASE GPIO_B_BASE +#define LEDS_CONF_RED 1 +#define LEDS_CONF_GREEN 2 +#define LEDS_CONF_BLUE 4 -#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 59484c2ff..000000000 --- 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 9f1bfe534..e25b08ef8 100644 --- a/examples/6tisch/6p-packet/6p-packet.csc +++ b/examples/6tisch/6p-packet/6p-packet.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/examples/6tisch/6p-packet/Makefile b/examples/6tisch/6p-packet/Makefile index 1ae6e34b5..7dcf9ccd3 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/sixp-node.c b/examples/6tisch/6p-packet/sixp-node.c index d911701bc..43cabbe29 100644 --- a/examples/6tisch/6p-packet/sixp-node.c +++ b/examples/6tisch/6p-packet/sixp-node.c @@ -30,11 +30,13 @@ #include #include -#include #include #include #include +/* Hard-coded MAC address of the TSCH coordinator */ +static linkaddr_t coordinator_addr = {{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}; + extern const sixtop_sf_t test_sf; extern int test_sf_start(const linkaddr_t *addr); @@ -49,7 +51,7 @@ PROCESS_THREAD(sixp_node_process, ev, data) 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/etsi-plugtest-2017/Makefile b/examples/6tisch/etsi-plugtest-2017/Makefile index f09edc0a7..3279b6ebc 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 578727d1f..3e16666dd 100644 --- a/examples/6tisch/etsi-plugtest-2017/node.c +++ b/examples/6tisch/etsi-plugtest-2017/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/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 +77,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/sf-plugtest.c b/examples/6tisch/etsi-plugtest-2017/sf-plugtest.c index 8c6628f3f..f4f54e6ac 100644 --- a/examples/6tisch/etsi-plugtest-2017/sf-plugtest.c +++ b/examples/6tisch/etsi-plugtest-2017/sf-plugtest.c @@ -314,7 +314,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, @@ -359,7 +359,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; } @@ -399,7 +399,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, @@ -446,7 +446,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; } @@ -489,7 +489,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, @@ -534,7 +534,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 +570,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( @@ -679,7 +679,7 @@ 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) { @@ -717,7 +717,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 fda05987f..e1102b2fa 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker [APPS_DIR]/radiologger-headless diff --git a/examples/6tisch/simple-node/Makefile b/examples/6tisch/simple-node/Makefile index e6cb76944..63ce8ecbd 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 9884b4e0e..4fa416290 100644 --- a/examples/6tisch/simple-node/node.c +++ b/examples/6tisch/simple-node/node.c @@ -38,15 +38,12 @@ #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 +66,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 +77,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/rpl-tsch-cooja.csc b/examples/6tisch/simple-node/rpl-tsch-cooja.csc index 276192cdd..bd5557214 100644 --- a/examples/6tisch/simple-node/rpl-tsch-cooja.csc +++ b/examples/6tisch/simple-node/rpl-tsch-cooja.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker [APPS_DIR]/radiologger-headless diff --git a/examples/6tisch/sixtop/Makefile b/examples/6tisch/sixtop/Makefile index 42360f170..5ca6be853 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 4c60db3a7..73e9fab2e 100755 --- a/examples/6tisch/sixtop/node-sixtop.c +++ b/examples/6tisch/sixtop/node-sixtop.c @@ -39,17 +39,13 @@ #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 +73,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 45e0a2fd1..7f416342e 100755 --- a/examples/6tisch/sixtop/project-conf.h +++ b/examples/6tisch/sixtop/project-conf.h @@ -82,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 diff --git a/examples/6tisch/sixtop/rpl-tsch-sixtop-cooja.csc b/examples/6tisch/sixtop/rpl-tsch-sixtop-cooja.csc index c0646919d..4ef875924 100644 --- a/examples/6tisch/sixtop/rpl-tsch-sixtop-cooja.csc +++ b/examples/6tisch/sixtop/rpl-tsch-sixtop-cooja.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker sixtop example diff --git a/examples/coap/Makefile b/examples/coap/Makefile index 1c8f2d21e..1195a37a3 100644 --- a/examples/coap/Makefile +++ b/examples/coap/Makefile @@ -1,40 +1,26 @@ -all: coap-example-server coap-example-client +CONTIKI_PROJECT = coap-example-server coap-example-client # use target "plugtest-server" explicitly when required +all: $(CONTIKI_PROJECT) + 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 +# Do not try to build on Sky because of code size limitation +PLATFORMS_EXCLUDE = sky -PROJECTDIRS += $(REST_RESOURCES_DIR) -PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES) +# build RESTful resources +include $(CONTIKI)/Makefile.identify-target +ifeq ($(TARGET),native) + MODULES_REL += ./resources-plugtest +endif +MODULES_REL += ./resources +MODULES_REL += $(TARGET) # 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) @@ -45,8 +31,8 @@ connect-router: $(CONTIKI)/tools/tunslip6 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-router-native: $(CONTIKI)/examples/rpl-border-router/border-router.native + sudo $(CONTIKI)/examples/rpl-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 +connect-native: + sudo ip address add fdfd::1/64 dev tun0 diff --git a/examples/coap/README.md b/examples/coap/README.md index f74ddfb9e..67ba38f26 100644 --- a/examples/coap/README.md +++ b/examples/coap/README.md @@ -1,109 +1,44 @@ -A Quick Introduction to the Erbium (Er) REST Engine +A Quick Introduction to the Erbium (Er) CoAP Engine =================================================== EXAMPLE FILES ------------- -- 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-server.c: A CoAP server example showing how to use the CoAP + layer to develop server-side applications. - 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). + Sophia-Antipolis, France, November 2012 (configured for native). 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 ------------ +TMOTE SKY HOWTO +--------------- -###Server only: +The CoAP example no longer fits in the limited ROM of the Tmote Sky. +Please use a platform with larger ROM instead. - 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 +NATIVE 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 +With the target native 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 +The plugtest-server is thought for the native platform, as it requires an 1280-byte IP buffer and 1024-byte blocks. - make TARGET=minimal-net plugtest-server - sudo ./plugtest-server.minimal-net + make TARGET=native plugtest-server + sudo ./plugtest-server.native Open new terminal - make connect-minimal + make connect-native - Start Copper and discover resources at coap://[fdfd::ff:fe00:10]:5683/ - You can enable the ETSI Plugtest menu in Copper's preferences @@ -130,12 +65,12 @@ 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 +- Blockwise Transfers (note COAP_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 +- Observing Resources (see EVENT_ and PERIODIC_RESOURCE, note COAP_MAX_OBSERVERS) TODOs diff --git a/examples/coap/coap-example-client.c b/examples/coap/coap-example-client.c index 5ef8f4fce..27efbbf6e 100644 --- a/examples/coap/coap-example-client.c +++ b/examples/coap/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 -#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 "client" +#define LOG_LEVEL LOG_LEVEL_COAP -#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-observe-client.c index 6d6b0c5cb..1dbed0bd4 100644 --- a/examples/coap/coap-example-observe-client.c +++ b/examples/coap/coap-example-observe-client.c @@ -42,26 +42,18 @@ #include "contiki.h" #include "contiki-net.h" #include "coap-engine.h" +#if PLATFORM_SUPPORTS_BUTTON_HAL +#include "dev/button-hal.h" +#else #include "dev/button-sensor.h" - +#endif /*----------------------------------------------------------------------------*/ #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]) #else #define PRINTF(...) -#define PRINT6ADDR(addr) #define PRINTFLN(...) #endif @@ -158,9 +150,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 +165,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/examples/coap/coap-example-server.c b/examples/coap/coap-example-server.c index 79c25d501..41ea53744 100644 --- a/examples/coap/coap-example-server.c +++ b/examples/coap/coap-example-server.c @@ -31,7 +31,7 @@ /** * \file - * Erbium (Er) REST Engine example. + * Erbium (Er) CoAP Engine example. * \author * Matthias Kovatsch */ @@ -40,10 +40,11 @@ #include #include #include "contiki.h" -#include "contiki-net.h" -#include "rest-engine.h" +#include "coap-engine.h" -#if PLATFORM_HAS_BUTTON +#if PLATFORM_SUPPORTS_BUTTON_HAL +#include "dev/button-hal.h" +#else #include "dev/button-sensor.h" #endif @@ -51,19 +52,15 @@ #if DEBUG #include #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 /* * 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,29 +70,29 @@ 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; +extern coap_resource_t res_battery; #endif #if PLATFORM_HAS_RADIO -extern resource_t res_radio; +extern coap_resource_t res_radio; #endif #if PLATFORM_HAS_SHT11 #include "dev/sht11/sht11-sensor.h" -extern resource_t res_sht11; +extern coap_resource_t res_sht11; #endif */ @@ -120,47 +117,49 @@ 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("CoAP max chunk: %u\n", COAP_MAX_CHUNK_SIZE); /* 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"); + coap_activate_resource(&res_radio, "sensors/radio"); #endif #if PLATFORM_HAS_SHT11 - rest_activate_resource(&res_sht11, "sensors/sht11"); - SENSORS_ACTIVATE(sht11_sensor); + coap_activate_resource(&res_sht11, "sensors/sht11"); + SENSORS_ACTIVATE(sht11_sensor); #endif */ @@ -168,7 +167,11 @@ PROCESS_THREAD(er_example_server, ev, data) 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) { +#endif PRINTF("*******BUTTON*******\n"); /* Call the event_handler for this application-specific event. */ diff --git a/examples/coap/in6addr.patch b/examples/coap/in6addr.patch deleted file mode 100644 index 92ca106cf..000000000 --- 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-server.c b/examples/coap/plugtest-server.c index c6c0e534f..7ca53bc2d 100644 --- a/examples/coap/plugtest-server.c +++ b/examples/coap/plugtest-server.c @@ -44,7 +44,7 @@ #include "coap.h" #include "coap-transactions.h" #include "coap-separate.h" -#include "rest-engine.h" +#include "coap-engine.h" #include "plugtest.h" /* @@ -52,7 +52,7 @@ * 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, @@ -95,29 +95,29 @@ PROCESS_THREAD(plugtest_server, ev, data) PRINTF("REST max chunk: %u\n", REST_MAX_CHUNK_SIZE); /* 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/examples/coap/plugtest.h b/examples/coap/plugtest.h index 78b168d4b..dff97282f 100644 --- a/examples/coap/plugtest.h +++ b/examples/coap/plugtest.h @@ -47,12 +47,8 @@ #if DEBUG #include #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 */ diff --git a/examples/coap/project-conf.h b/examples/coap/project-conf.h index d8a3b1122..115d6fbb0 100644 --- a/examples/coap/project-conf.h +++ b/examples/coap/project-conf.h @@ -36,43 +36,37 @@ * Matthias Kovatsch */ -#ifndef __PROJECT_ERBIUM_CONF_H__ -#define __PROJECT_ERBIUM_CONF_H__ +#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 - */ +/* #define RF_CHANNEL 26 */ +/* #define IEEE802154_CONF_PANID 0xABCD */ /* IP buffer size must match all other hops, in particular the border router. */ -/* - #define UIP_CONF_BUFFER_SIZE 256 - */ +/* #define UIP_CONF_BUFFER_SIZE 256 */ /* Increase rpl-border-router IP-buffer when using more than 64. */ -#define REST_MAX_CHUNK_SIZE 48 +#define COAP_MAX_CHUNK_SIZE 48 /* Estimate your header size, especially when using Proxy-Uri. */ -/* - #define COAP_MAX_HEADER_SIZE 70 - */ +/* #define COAP_MAX_HEADER_SIZE 70 */ /* Multiplies with chunk size, be aware of memory constraints. */ +#ifndef COAP_MAX_OPEN_TRANSACTIONS #define COAP_MAX_OPEN_TRANSACTIONS 4 +#endif /* COAP_MAX_OPEN_TRANSACTIONS */ /* Must be <= open transactions, default is COAP_MAX_OPEN_TRANSACTIONS-1. */ -/* - #define COAP_MAX_OBSERVERS 2 - */ +/* #define COAP_MAX_OBSERVERS 2 */ /* 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 - /* Enable client-side support for COAP observe */ -#define COAP_OBSERVE_CLIENT 1 -#endif /* __PROJECT_ERBIUM_CONF_H__ */ +#ifndef COAP_OBSERVE_CLIENT +#define COAP_OBSERVE_CLIENT 1 +#endif /* COAP_OBSERVE_CLIENT */ + +#endif /* PROJECT_ERBIUM_CONF_H_ */ diff --git a/examples/coap/resources/res-plugtest-create1.c b/examples/coap/resources-plugtest/res-plugtest-create1.c similarity index 74% rename from examples/coap/resources/res-plugtest-create1.c rename to examples/coap/resources-plugtest/res-plugtest-create1.c index 4e8c52231..50f48a09e 100644 --- a/examples/coap/resources/res-plugtest-create1.c +++ b/examples/coap/resources-plugtest/res-plugtest-create1.c @@ -37,12 +37,12 @@ */ #include -#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); +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 +54,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"); 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); + coap_set_status_code(response, DELETED_2_02); create1_exists = 0; } diff --git a/examples/coap/resources/res-plugtest-create2.c b/examples/coap/resources-plugtest/res-plugtest-create2.c similarity index 82% rename from examples/coap/resources/res-plugtest-create2.c rename to examples/coap/resources-plugtest/res-plugtest-create2.c index 714432ff6..169f47812 100644 --- a/examples/coap/resources/res-plugtest-create2.c +++ b/examples/coap/resources-plugtest/res-plugtest-create2.c @@ -37,11 +37,11 @@ */ #include -#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); +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 +51,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 "); - 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/resources-plugtest/res-plugtest-create3.c similarity index 74% rename from examples/coap/resources/res-plugtest-create3.c rename to examples/coap/resources-plugtest/res-plugtest-create3.c index fe7526eba..178a0089e 100644 --- a/examples/coap/resources/res-plugtest-create3.c +++ b/examples/coap/resources-plugtest/res-plugtest-create3.c @@ -37,12 +37,12 @@ */ #include -#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); +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 +54,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 "); 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); + 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/resources-plugtest/res-plugtest-large-create.c similarity index 72% rename from examples/coap/resources/res-plugtest-large-create.c rename to examples/coap/resources-plugtest/res-plugtest-large-create.c index ac1e27a3d..78d21b69b 100644 --- a/examples/coap/resources/res-plugtest-large-create.c +++ b/examples/coap/resources-plugtest/res-plugtest-large-create.c @@ -37,11 +37,11 @@ */ #include -#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); +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 +54,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/resources-plugtest/res-plugtest-large-update.c similarity index 71% rename from examples/coap/resources/res-plugtest-large-update.c rename to examples/coap/resources-plugtest/res-plugtest-large-update.c index 8263ccc2a..a79978be1 100644 --- a/examples/coap/resources/res-plugtest-large-update.c +++ b/examples/coap/resources-plugtest/res-plugtest-large-update.c @@ -36,14 +36,15 @@ * Matthias Kovatsch */ +#include #include #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); +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 +59,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 +84,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 +107,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 +121,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/resources-plugtest/res-plugtest-large.c similarity index 85% rename from examples/coap/resources/res-plugtest-large.c rename to examples/coap/resources-plugtest/res-plugtest-large.c index 8a7372eb8..f828e4dbe 100644 --- a/examples/coap/resources/res-plugtest-large.c +++ b/examples/coap/resources-plugtest/res-plugtest-large.c @@ -36,12 +36,13 @@ * Matthias Kovatsch */ +#include #include -#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_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 +52,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 +80,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/resources-plugtest/res-plugtest-links.c similarity index 85% rename from examples/coap/resources/res-plugtest-links.c rename to examples/coap/resources-plugtest/res-plugtest-links.c index f802d3c56..99315a17f 100644 --- a/examples/coap/resources/res-plugtest-links.c +++ b/examples/coap/resources-plugtest/res-plugtest-links.c @@ -37,11 +37,11 @@ */ #include -#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_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 +63,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/resources-plugtest/res-plugtest-locquery.c similarity index 82% rename from examples/coap/resources/res-plugtest-locquery.c rename to examples/coap/resources-plugtest/res-plugtest-locquery.c index d75a9a620..e93ef8b65 100644 --- a/examples/coap/resources/res-plugtest-locquery.c +++ b/examples/coap/resources-plugtest/res-plugtest-locquery.c @@ -37,11 +37,11 @@ */ #include -#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); +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 +51,15 @@ 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; + coap_message_t *const coap_req = (coap_message_t *)request; #endif PRINTF( "/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/resources-plugtest/res-plugtest-longpath.c similarity index 83% rename from examples/coap/resources/res-plugtest-longpath.c rename to examples/coap/resources-plugtest/res-plugtest-longpath.c index 5a26d4db9..7a1271321 100644 --- a/examples/coap/resources/res-plugtest-longpath.c +++ b/examples/coap/resources-plugtest/res-plugtest-longpath.c @@ -36,12 +36,14 @@ * Matthias Kovatsch */ + +#include #include -#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_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,14 +53,14 @@ 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 "); /* 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-multi.c b/examples/coap/resources-plugtest/res-plugtest-multi.c similarity index 77% rename from examples/coap/resources/res-plugtest-multi.c rename to examples/coap/resources-plugtest/res-plugtest-multi.c index c6592b397..f0a388430 100644 --- a/examples/coap/resources/res-plugtest-multi.c +++ b/examples/coap/resources-plugtest/res-plugtest-multi.c @@ -36,12 +36,13 @@ * Matthias Kovatsch */ +#include #include -#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_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,27 +52,27 @@ 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); - 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( + } else if(accept == APPLICATION_XML) { + coap_set_header_content_format(response, APPLICATION_XML); + coap_set_payload( response, buffer, snprintf((char *)buffer, MAX_PLUGFEST_PAYLOAD, @@ -79,9 +80,9 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr coap_req->type, coap_req->code, coap_req->mid, accept)); PRINTF("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)); + coap_set_payload(response, msg, strlen(msg)); PRINTF("ERROR\n"); } } diff --git a/examples/coap/resources/res-plugtest-obs.c b/examples/coap/resources-plugtest/res-plugtest-obs.c similarity index 70% rename from examples/coap/resources/res-plugtest-obs.c rename to examples/coap/resources-plugtest/res-plugtest-obs.c index 74d61d894..d60aaec04 100644 --- a/examples/coap/resources/res-plugtest-obs.c +++ b/examples/coap/resources-plugtest/res-plugtest-obs.c @@ -36,15 +36,16 @@ * Matthias Kovatsch */ +#include #include -#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); +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, @@ -67,35 +68,35 @@ static void obs_purge_list() { PRINTF("### SERVER ACTION ### Purging obs list"); - coap_remove_observer_by_uri(NULL, 0, res_plugtest_obs.url); + 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"); } - 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"); @@ -103,26 +104,26 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr 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"); 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() @@ -134,7 +135,7 @@ res_periodic_handler() 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"); @@ -142,7 +143,7 @@ res_periodic_handler() } 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 +151,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/resources-plugtest/res-plugtest-path.c similarity index 82% rename from examples/coap/resources/res-plugtest-path.c rename to examples/coap/resources-plugtest/res-plugtest-path.c index 03eb362bb..fac05ccb0 100644 --- a/examples/coap/resources/res-plugtest-path.c +++ b/examples/coap/resources-plugtest/res-plugtest-path.c @@ -36,12 +36,13 @@ * Matthias Kovatsch */ +#include #include -#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_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 +52,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, ",,"); } 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/resources-plugtest/res-plugtest-query.c similarity index 81% rename from examples/coap/resources/res-plugtest-query.c rename to examples/coap/resources-plugtest/res-plugtest-query.c index 6ffbccbbb..10df145b3 100644 --- a/examples/coap/resources/res-plugtest-query.c +++ b/examples/coap/resources-plugtest/res-plugtest-query.c @@ -36,12 +36,13 @@ * Matthias Kovatsch */ +#include #include -#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_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 +52,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( "/query GET (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); - if((len = REST.get_query(request, &query))) { + if((len = coap_get_header_uri_query(request, &query))) { PRINTF("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/resources-plugtest/res-plugtest-separate.c similarity index 88% rename from examples/coap/resources/res-plugtest-separate.c rename to examples/coap/resources-plugtest/res-plugtest-separate.c index b45841ec1..16aa267ce 100644 --- a/examples/coap/resources/res-plugtest-separate.c +++ b/examples/coap/resources-plugtest/res-plugtest-separate.c @@ -36,14 +36,15 @@ * Matthias Kovatsch */ +#include #include -#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); +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,9 +68,9 @@ 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 "); if(separate_active) { @@ -97,17 +98,16 @@ res_resume_handler() PRINTF("/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))) { + &separate_store->request_metadata.endpoint))) { PRINTF( "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,8 +120,8 @@ 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). */ diff --git a/examples/coap/resources/res-plugtest-test.c b/examples/coap/resources-plugtest/res-plugtest-test.c similarity index 68% rename from examples/coap/resources/res-plugtest-test.c rename to examples/coap/resources-plugtest/res-plugtest-test.c index 4af32b9ba..f7ac97c83 100644 --- a/examples/coap/resources/res-plugtest-test.c +++ b/examples/coap/resources-plugtest/res-plugtest-test.c @@ -36,15 +36,17 @@ * Matthias Kovatsch */ +#include #include -#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); +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); @@ -69,9 +71,9 @@ test_update_etag() 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]); } 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(); @@ -82,48 +84,48 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr && 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); + 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"); } 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; + coap_message_t *const coap_req = (coap_message_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_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; + coap_message_t *const coap_req = (coap_message_t *)request; PRINTF("/test PUT (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); #endif 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"); } 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"); @@ -133,9 +135,9 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr && 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; @@ -148,15 +150,15 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr 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; + coap_message_t *const coap_req = (coap_message_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_set_status_code(response, DELETED_2_02); } diff --git a/examples/coap/resources/res-plugtest-validate.c b/examples/coap/resources-plugtest/res-plugtest-validate.c similarity index 77% rename from examples/coap/resources/res-plugtest-validate.c rename to examples/coap/resources-plugtest/res-plugtest-validate.c index ab7b6cfca..30d97e727 100644 --- a/examples/coap/resources/res-plugtest-validate.c +++ b/examples/coap/resources-plugtest/res-plugtest-validate.c @@ -36,13 +36,15 @@ * Matthias Kovatsch */ +#include #include -#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); +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\"", @@ -72,9 +74,9 @@ validate_update_etag() 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(); @@ -85,17 +87,17 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr 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); + 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"); } 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,10 +106,10 @@ 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; + coap_message_t *const coap_req = (coap_message_t *)request; #endif PRINTF("/validate PUT "); @@ -118,9 +120,9 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr && 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; @@ -134,6 +136,6 @@ res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr 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/resources/res-b1-sep-b2.c b/examples/coap/resources/res-b1-sep-b2.c index 26b6b8606..0fa76726f 100644 --- a/examples/coap/resources/res-b1-sep-b2.c +++ b/examples/coap/resources/res-b1-sep-b2.c @@ -36,13 +36,14 @@ * Lars Schmertmann */ +#include #include -#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/resources/res-battery.c index b82523594..b4c7623b3 100644 --- a/examples/coap/resources/res-battery.c +++ b/examples/coap/resources/res-battery.c @@ -41,10 +41,11 @@ #if PLATFORM_HAS_BATTERY #include -#include "rest-engine.h" +#include +#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/resources/res-chunks.c index 13de706c8..39555d091 100644 --- a/examples/coap/resources/res-chunks.c +++ b/examples/coap/resources/res-chunks.c @@ -36,13 +36,14 @@ * Matthias Kovatsch */ +#include #include -#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/resources/res-event.c index 35ff1f8eb..5640353b3 100644 --- a/examples/coap/resources/res-event.c +++ b/examples/coap/resources/res-event.c @@ -36,8 +36,9 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #define DEBUG 0 @@ -52,7 +53,7 @@ #define PRINTLLADDR(addr) #endif -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 +75,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. */ } @@ -96,6 +97,6 @@ res_event_handler(void) PRINTF("TICK %u for /%s\n", 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/resources/res-hello.c index 9208f8b74..46b0139ef 100644 --- a/examples/coap/resources/res-hello.c +++ b/examples/coap/resources/res-hello.c @@ -38,9 +38,9 @@ #include #include -#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,7 @@ 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/resources/res-leds.c index 5fbcf6c77..d601e49f5 100644 --- a/examples/coap/resources/res-leds.c +++ b/examples/coap/resources/res-leds.c @@ -37,12 +37,12 @@ */ #include "contiki.h" - -#if PLATFORM_HAS_LEDS +#include "coap-engine.h" +#include "dev/leds.h" #include -#include "rest-engine.h" -#include "dev/leds.h" + +#if PLATFORM_HAS_LEDS || LEDS_COUNT #define DEBUG 0 #if DEBUG @@ -56,9 +56,9 @@ #define PRINTLLADDR(addr) #endif -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 +67,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,7 +75,7 @@ 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))) { + if((len = coap_get_query_variable(request, "color", &color))) { PRINTF("color %.*s\n", len, color); if(strncmp(color, "r", len) == 0) { @@ -89,7 +89,7 @@ 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))) { + } if(success && (len = coap_get_post_variable(request, "mode", &mode))) { PRINTF("mode %s\n", mode); if(strncmp(mode, "on", len) == 0) { @@ -102,7 +102,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/resources/res-light.c index 226d814bb..3384b2e5f 100644 --- a/examples/coap/resources/res-light.c +++ b/examples/coap/resources/res-light.c @@ -40,11 +40,12 @@ #if PLATFORM_HAS_LIGHT +#include #include -#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, 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, 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/resources/res-mirror.c index 15b7c3b80..1ba948b0d 100644 --- a/examples/coap/resources/res-mirror.c +++ b/examples/coap/resources/res-mirror.c @@ -36,8 +36,9 @@ * Matthias Kovatsch */ +#include #include -#include "rest-engine.h" +#include "coap-engine.h" #include "coap.h" #define DEBUG 0 @@ -52,7 +53,7 @@ #define PRINTLLADDR(addr) #endif -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 +64,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 +90,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 +122,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 +133,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 +150,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); /* 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/resources/res-push.c index 120e2ffef..ffc8c9c07 100644 --- a/examples/coap/resources/res-push.c +++ b/examples/coap/resources/res-push.c @@ -36,11 +36,12 @@ * Matthias Kovatsch */ +#include #include -#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/resources/res-radio.c index b33bf703a..c23436bb6 100644 --- a/examples/coap/resources/res-radio.c +++ b/examples/coap/resources/res-radio.c @@ -39,12 +39,12 @@ #include "contiki.h" #if PLATFORM_HAS_RADIO - +#include #include -#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/resources/res-separate.c index fb402d2b9..6b98345bb 100644 --- a/examples/coap/resources/res-separate.c +++ b/examples/coap/resources/res-separate.c @@ -37,11 +37,12 @@ */ #include -#include "rest-engine.h" +#include +#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/resources/res-sht11.c index 56ed86c01..4dcf30e70 100644 --- a/examples/coap/resources/res-sht11.c +++ b/examples/coap/resources/res-sht11.c @@ -43,11 +43,12 @@ #if PLATFORM_HAS_SHT11 +#include #include -#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, 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, 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/resources/res-sub.c index 1d6f17aeb..88bc6a584 100644 --- a/examples/coap/resources/res-sub.c +++ b/examples/coap/resources/res-sub.c @@ -36,14 +36,15 @@ * Matthias Kovatsch */ +#include #include -#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/resources/res-temperature.c index c8bce8ba8..ac34dbe33 100644 --- a/examples/coap/resources/res-temperature.c +++ b/examples/coap/resources/res-temperature.c @@ -44,11 +44,12 @@ #include #include +#include #include -#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/resources/res-toggle.c index d8a773306..b90ac77c7 100644 --- a/examples/coap/resources/res-toggle.c +++ b/examples/coap/resources/res-toggle.c @@ -37,15 +37,14 @@ */ #include "contiki.h" - -#if PLATFORM_HAS_LEDS - -#include -#include "contiki.h" -#include "rest-engine.h" +#include "coap-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); +#include + +#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/server-client-native.csc b/examples/coap/server-client-native.csc deleted file mode 100644 index cec9ca8a7..000000000 --- a/examples/coap/server-client-native.csc +++ /dev/null @@ -1,231 +0,0 @@ - - - [APPS_DIR]/mrm - [APPS_DIR]/mspsim - [APPS_DIR]/avrora - [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view - [APPS_DIR]/powertracker - - REST with RPL router - 1.0 - 123456 - 1000000 - - org.contikios.cooja.radiomediums.UDGM - 50.0 - 50.0 - 1.0 - 1.0 - - - 40000 - - - org.contikios.cooja.mspmote.SkyMoteType - slipradio - Sky SLIP radio - [CONTIKI_DIR]/examples/ipv6/slip-radio/slip-radio.c - make slip-radio.sky TARGET=sky - [CONTIKI_DIR]/examples/ipv6/slip-radio/slip-radio.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - server - Erbium Server - [CONTIKI_DIR]/examples/coap/coap-example-server.c - make coap-example-server.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-server.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - client - Erbium Client - [CONTIKI_DIR]/examples/coap/coap-example-client.c - make coap-example-client.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-client.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - - - org.contikios.cooja.interfaces.Position - 30.303994886410642 - 17.22128424003353 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 1 - - slipradio - - - - - org.contikios.cooja.interfaces.Position - 46.57186415376375 - 37.25589203828498 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 2 - - server - - - - - org.contikios.cooja.interfaces.Position - 18.194682268367348 - 50.210548118402656 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 3 - - client - - - - org.contikios.cooja.plugins.SimControl - 259 - 0 - 179 - 1 - 2 - - - org.contikios.cooja.plugins.Visualizer - - org.contikios.cooja.plugins.skins.IDVisualizerSkin - org.contikios.cooja.plugins.skins.UDGMVisualizerSkin - org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin - org.contikios.cooja.plugins.skins.AttributeVisualizerSkin - org.contikios.cooja.plugins.skins.LEDVisualizerSkin - org.contikios.cooja.plugins.skins.AddressVisualizerSkin - 2.255467003316979 0.0 0.0 2.255467003316979 59.30641698643764 -13.478401994502008 - - 300 - 2 - 178 - 262 - 1 - - - org.contikios.cooja.plugins.LogListener - - - - - - 762 - 4 - 491 - 2 - 182 - - - org.contikios.cooja.plugins.RadioLogger - - 150 - - false - false - - - 451 - -1 - 305 - 73 - 140 - true - - - org.contikios.cooja.plugins.TimeLine - - 0 - 1 - 2 - - - - - 25.49079397896416 - - 1624 - 5 - 252 - 6 - 712 - - - org.contikios.cooja.plugins.MoteInterfaceViewer - 1 - - Serial port - 0,0 - - 853 - 3 - 491 - 765 - 182 - - - org.contikios.cooja.serialsocket.SerialSocketServer - 0 - 422 - 1 - 82 - 606 - 51 - - - diff --git a/examples/coap/server-client-observe.csc b/examples/coap/server-client-observe.csc deleted file mode 100644 index a7c9cca8b..000000000 --- a/examples/coap/server-client-observe.csc +++ /dev/null @@ -1,203 +0,0 @@ - - - [APPS_DIR]/mrm - [APPS_DIR]/mspsim - [APPS_DIR]/avrora - [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view - [APPS_DIR]/powertracker - - REST with RPL router - 1.0 - 123456 - 1000000 - - org.contikios.cooja.radiomediums.UDGM - 50.0 - 50.0 - 1.0 - 1.0 - - - 40000 - - - org.contikios.cooja.mspmote.SkyMoteType - rplroot - Sky RPL Root - [CONTIKI_DIR]/examples/rpl-border-router/border-router.c - make border-router.sky TARGET=sky - [CONTIKI_DIR]/examples/rpl-border-router/border-router.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - server - Erbium Server - [CONTIKI_DIR]/examples/coap/coap-example-server.c - make coap-example-server.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-server.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - client - Erbium Client - [CONTIKI_DIR]/examples/coap/coap-example-observe-client.c - make coap-example-observe-client.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-observe-client.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - - - org.contikios.cooja.interfaces.Position - 33.260163187353555 - 30.643217359962595 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 1 - - rplroot - - - - - org.contikios.cooja.interfaces.Position - 54.537149936813485 - 51.51086225537906 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 2 - - server - - - - - org.contikios.cooja.interfaces.Position - 77.97942851220571 - 67.86182390447284 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 3 - - client - - - - org.contikios.cooja.plugins.SimControl - 259 - 3 - 179 - 2 - 1 - - - org.contikios.cooja.plugins.Visualizer - - org.contikios.cooja.plugins.skins.IDVisualizerSkin - org.contikios.cooja.plugins.skins.UDGMVisualizerSkin - org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin - org.contikios.cooja.plugins.skins.AttributeVisualizerSkin - org.contikios.cooja.plugins.skins.LEDVisualizerSkin - org.contikios.cooja.plugins.skins.AddressVisualizerSkin - 2.092412892721766 0.0 0.0 2.092412892721766 34.70057915472623 -45.606066372444175 - - 300 - 4 - 178 - 261 - 1 - - - org.contikios.cooja.plugins.LogListener - - - - - - 762 - 0 - 491 - 2 - 182 - - - org.contikios.cooja.plugins.RadioLogger - - 167 - - false - false - - - 560 - 1 - 492 - 764 - 181 - - - org.contikios.cooja.serialsocket.SerialSocketServer - 0 - - 60001 - true - - 362 - 2 - 116 - 561 - 1 - - - diff --git a/examples/coap/server-client.csc b/examples/coap/server-client.csc deleted file mode 100644 index a649d048a..000000000 --- a/examples/coap/server-client.csc +++ /dev/null @@ -1,231 +0,0 @@ - - - [APPS_DIR]/mrm - [APPS_DIR]/mspsim - [APPS_DIR]/avrora - [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view - [APPS_DIR]/powertracker - - REST with RPL router - 1.0 - 123456 - 1000000 - - org.contikios.cooja.radiomediums.UDGM - 50.0 - 50.0 - 1.0 - 1.0 - - - 40000 - - - org.contikios.cooja.mspmote.SkyMoteType - rplroot - Sky RPL Root - [CONTIKI_DIR]/examples/rpl-border-router/border-router.c - make border-router.sky TARGET=sky - [CONTIKI_DIR]/examples/rpl-border-router/border-router.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - server - Erbium Server - [CONTIKI_DIR]/examples/coap/coap-example-server.c - make coap-example-server.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-server.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - client - Erbium Client - [CONTIKI_DIR]/examples/coap/coap-example-client.c - make coap-example-client.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-client.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - - - org.contikios.cooja.interfaces.Position - 33.260163187353555 - 30.643217359962595 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 1 - - rplroot - - - - - org.contikios.cooja.interfaces.Position - 46.57186415376375 - 40.35946215910942 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 2 - - server - - - - - org.contikios.cooja.interfaces.Position - 18.638049428485125 - 47.55034515769599 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 3 - - client - - - - org.contikios.cooja.plugins.SimControl - 259 - 0 - 179 - 2 - 1 - - - org.contikios.cooja.plugins.Visualizer - - org.contikios.cooja.plugins.skins.IDVisualizerSkin - org.contikios.cooja.plugins.skins.UDGMVisualizerSkin - org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin - org.contikios.cooja.plugins.skins.AttributeVisualizerSkin - org.contikios.cooja.plugins.skins.LEDVisualizerSkin - org.contikios.cooja.plugins.skins.AddressVisualizerSkin - 3.61568947862321 0.0 0.0 3.61568947862321 15.610600779367 -85.92728269158351 - - 300 - 2 - 178 - 261 - 1 - - - org.contikios.cooja.plugins.LogListener - - - - - - 762 - 3 - 491 - 2 - 182 - - - org.contikios.cooja.plugins.RadioLogger - - 150 - - false - false - - - 451 - -1 - 305 - 73 - 140 - true - - - org.contikios.cooja.serialsocket.SerialSocketServer - 0 - 422 - 4 - 74 - 578 - 18 - - - org.contikios.cooja.plugins.TimeLine - - 0 - 1 - 2 - - - - - 25.49079397896416 - - 1624 - 5 - 252 - 6 - 712 - - - org.contikios.cooja.plugins.MoteInterfaceViewer - 2 - - Serial port - 0,0 - - 853 - 1 - 491 - 765 - 182 - - - diff --git a/examples/coap/server-only.csc b/examples/coap/server-only.csc deleted file mode 100644 index 715deae1c..000000000 --- a/examples/coap/server-only.csc +++ /dev/null @@ -1,193 +0,0 @@ - - - [APPS_DIR]/mrm - [APPS_DIR]/mspsim - [APPS_DIR]/avrora - [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view - [APPS_DIR]/powertracker - - REST with RPL router - 1.0 - 123456 - 1000000 - - org.contikios.cooja.radiomediums.UDGM - 50.0 - 50.0 - 1.0 - 1.0 - - - 40000 - - - org.contikios.cooja.mspmote.SkyMoteType - rplroot - Sky RPL Root - [CONTIKI_DIR]/examples/rpl-border-router/border-router.c - make border-router.sky TARGET=sky - [CONTIKI_DIR]/examples/rpl-border-router/border-router.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - server - Erbium Server - [CONTIKI_DIR]/examples/coap/coap-example-server.c - make coap-example-server.sky TARGET=sky - [CONTIKI_DIR]/examples/coap/coap-example-server.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - - - org.contikios.cooja.interfaces.Position - 33.260163187353555 - 30.643217359962595 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 1 - - rplroot - - - - - org.contikios.cooja.interfaces.Position - 35.100895239785295 - 39.70574552287428 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 2 - - server - - - - org.contikios.cooja.plugins.SimControl - 259 - 0 - 179 - 2 - 1 - - - org.contikios.cooja.plugins.Visualizer - - org.contikios.cooja.plugins.skins.IDVisualizerSkin - org.contikios.cooja.plugins.skins.UDGMVisualizerSkin - org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin - org.contikios.cooja.plugins.skins.AttributeVisualizerSkin - org.contikios.cooja.plugins.skins.LEDVisualizerSkin - org.contikios.cooja.plugins.skins.AddressVisualizerSkin - 7.9849281638410705 0.0 0.0 7.9849281638410705 -133.27812697619663 -225.04752569190535 - - 300 - 1 - 175 - 262 - 2 - - - org.contikios.cooja.plugins.LogListener - - - - - - 560 - 3 - 326 - 1 - 293 - - - org.contikios.cooja.plugins.RadioLogger - - 150 - - false - false - - - 451 - -1 - 305 - 73 - 140 - true - - - org.contikios.cooja.serialsocket.SerialSocketServer - 0 - 422 - 4 - 74 - 39 - 199 - - - org.contikios.cooja.plugins.TimeLine - - 0 - 1 - - - - - 25.49079397896416 - - 1624 - 5 - 252 - 4 - 622 - - - org.contikios.cooja.plugins.MoteInterfaceViewer - 1 - - Serial port - 0,0 - - 702 - 2 - 646 - 564 - 2 - - - diff --git a/examples/coap/sky/module-macros.h b/examples/coap/sky/module-macros.h new file mode 100644 index 000000000..3fcb04015 --- /dev/null +++ b/examples/coap/sky/module-macros.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018, 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. + */ + +#error The CoAP example no longer fits the limited ROM in the Tmote Sky. \ + Please select another platform with more ROM to compile the CoAP example. + +/*---------------------------------------------------------------------------*/ +#define COAP_OBSERVE_CLIENT 0 + +#define COAP_MAX_CHUNK_SIZE 48 + +/* Turn off DAO-ACK and probing to make code smaller */ +#define RPL_CONF_WITH_DAO_ACK 0 + +#define LOG_CONF_LEVEL_MAIN 0 + +#define DCOSYNCH_CONF_ENABLED 0 + +#define PROCESS_CONF_NUMEVENTS 8 +/*---------------------------------------------------------------------------*/ diff --git a/examples/dev/button-hal/Makefile b/examples/dev/button-hal/Makefile new file mode 100644 index 000000000..071ec02ec --- /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 + +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 000000000..d741ec73c --- /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 000000000..b4d584e3e --- /dev/null +++ b/examples/dev/button-hal/button-hal-example.c @@ -0,0 +1,83 @@ +/* + * 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 +/*---------------------------------------------------------------------------*/ +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); + 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 000000000..457b42bfc --- /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 000000000..efbdf6e05 --- /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 + +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 000000000..84ab68f88 --- /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 000000000..4cb3e9742 --- /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 000000000..040df3b38 --- /dev/null +++ b/examples/dev/gpio-hal/gpio-hal-example.c @@ -0,0 +1,140 @@ +/* + * 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 +/*---------------------------------------------------------------------------*/ +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; +/*---------------------------------------------------------------------------*/ +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%08lx\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/openmote-cc2538/pins.c b/examples/dev/gpio-hal/openmote-cc2538/pins.c new file mode 100644 index 000000000..340aff15c --- /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 000000000..700f8961b --- /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/slip-radio/sky/target-conf.h b/examples/dev/gpio-hal/zoul/pins.c similarity index 85% rename from examples/slip-radio/sky/target-conf.h rename to examples/dev/gpio-hal/zoul/pins.c index 08fa66512..ff44bf4d1 100644 --- a/examples/slip-radio/sky/target-conf.h +++ b/examples/dev/gpio-hal/zoul/pins.c @@ -29,15 +29,12 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -#ifndef TARGET_CONF_H_ -#define TARGET_CONF_H_ +#include "contiki.h" +#include "dev/gpio-hal.h" /*---------------------------------------------------------------------------*/ -#define QUEUEBUF_CONF_NUM 4 -#define UIP_CONF_BUFFER_SIZE 140 - -#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 +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; /*---------------------------------------------------------------------------*/ -#endif /* TARGET_CONF_H_ */ +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 000000000..7c5f5f592 --- /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 000000000..05bdc20ba --- /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 000000000..b62668e8b --- /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 +/*---------------------------------------------------------------------------*/ +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 000000000..e2142cf2d --- /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 000000000..75430a6e4 --- /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 000000000..1b10926ce --- /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 000000000..e2c2de21e --- /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 +/*---------------------------------------------------------------------------*/ +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/http-socket/Makefile b/examples/http-socket/Makefile index e1904d3ab..87d0789c1 100644 --- a/examples/http-socket/Makefile +++ b/examples/http-socket/Makefile @@ -1,5 +1,8 @@ -all: http-example websocket-example +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/websocket-node/Makefile b/examples/http-socket/websocket-node/Makefile index cde795492..9dcc1def8 100644 --- a/examples/http-socket/websocket-node/Makefile +++ b/examples/http-socket/websocket-node/Makefile @@ -4,3 +4,10 @@ install: run: nodejs example-server.js + +# Needed by the build all script +all: + true + +clean: + rm -rf node_modules diff --git a/examples/ip64-router/Makefile b/examples/ip64-router/Makefile index a77652cfa..0beea11bd 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 a6a5af450..632b9ba2e 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 index d4a1ef503..d77f4200a 100644 --- a/examples/ipso-objects/Makefile +++ b/examples/ipso-objects/Makefile @@ -2,6 +2,8 @@ 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 diff --git a/examples/ipso-objects/example-ipso-objects.c b/examples/ipso-objects/example-ipso-objects.c index 180369076..013c62205 100644 --- a/examples/ipso-objects/example-ipso-objects.c +++ b/examples/ipso-objects/example-ipso-objects.c @@ -37,8 +37,16 @@ */ #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" @@ -52,9 +60,84 @@ #endif #ifndef LWM2M_SERVER_ADDRESS -#define LWM2M_SERVER_ADDRESS "fd00::1" +#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); /*---------------------------------------------------------------------------*/ @@ -62,39 +145,70 @@ 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); + 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_engine_use_bootstrap_server(REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER); - lwm2m_engine_use_registration_server(REGISTER_WITH_LWM2M_SERVER); + 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\n"); - + 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_engine_register_default_objects(); + lwm2m_device_init(); + lwm2m_security_init(); + lwm2m_server_init(); - /* Register default IPSO objects */ +#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-server.c b/examples/ipso-objects/example-server.c index acec7ee25..4eac38f69 100644 --- a/examples/ipso-objects/example-server.c +++ b/examples/ipso-objects/example-server.c @@ -38,13 +38,12 @@ #include "contiki.h" #include "net/ipv6/uip.h" -#include "rpl.h" -#include "rpl-dag-root.h" #include "net/netstack.h" +#include "net/routing/routing.h" #include "coap-constants.h" #include "coap-engine.h" #include "lwm2m-engine.h" -#include "oma-tlv.h" +#include "lwm2m-tlv.h" #include "dev/serial-line.h" #include "serial-protocol.h" @@ -187,13 +186,13 @@ client_chunk_handler(void *response) } 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); + int value = lwm2m_tlv_get_int32(&tlv); snprintf(current_value, sizeof(current_value), "%d", value); } } else { @@ -237,8 +236,8 @@ setup_network(void) uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); #endif - rpl_dag_root_init(&ipaddr, &ipaddr); - rpl_dag_root_init_dag_immediately(); + NETSTACK_ROUTING.root_set_prefix(&ipaddr, &ipaddr); + NETSTACK_ROUTING.root_start(); #endif /* UIP_CONF_ROUTER */ PRINTF("IPv6 addresses: "); @@ -257,8 +256,8 @@ setup_network(void) /*---------------------------------------------------------------------------*/ 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; @@ -269,7 +268,7 @@ PROCESS_THREAD(router_process, ev, data) PROCESS_PAUSE(); /* receives all CoAP messages */ - coap_init_engine(); + coap_engine_init(); setup_network(); diff --git a/examples/ipso-objects/project-conf.h b/examples/ipso-objects/project-conf.h index 075cd7444..a7ad8b3ea 100644 --- a/examples/ipso-objects/project-conf.h +++ b/examples/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/ipv6-hooks/Makefile b/examples/ipv6-hooks/Makefile index bbd4b7168..be8cc953e 100644 --- a/examples/ipv6-hooks/Makefile +++ b/examples/ipv6-hooks/Makefile @@ -1,4 +1,5 @@ -all: ipv6-hooks +CONTIKI_PROJECT = ipv6-hooks +all: $(CONTIKI_PROJECT) CONTIKI=../.. include $(CONTIKI)/Makefile.include diff --git a/examples/ipv6-hooks/ipv6-hooks.c b/examples/ipv6-hooks/ipv6-hooks.c index 30269b030..d3ca8861c 100644 --- a/examples/ipv6-hooks/ipv6-hooks.c +++ b/examples/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 d394c0bc4..eead5bc90 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 f42f08723..8f393c319 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 index 243679d51..02b94cfc0 100644 --- a/examples/libs/stack-check/Makefile +++ b/examples/libs/stack-check/Makefile @@ -1,5 +1,7 @@ CONTIKI_PROJECT = example-stack-check all: $(CONTIKI_PROJECT) +PLATFORMS_EXCLUDE = native cooja + CONTIKI = ../../.. include $(CONTIKI)/Makefile.include diff --git a/examples/libs/trickle-library/trickle-library.c b/examples/libs/trickle-library/trickle-library.c index 30e02caf0..c449aade9 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 @@ -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 bea3f6c3e..a450f15e8 100644 --- a/examples/libs/trickle-library/trickle-library.csc +++ b/examples/libs/trickle-library/trickle-library.csc @@ -4,7 +4,6 @@ [CONTIKI_DIR]/tools/cooja/apps/mspsim [CONTIKI_DIR]/tools/cooja/apps/avrora [CONTIKI_DIR]/tools/cooja/apps/serial_socket - [CONTIKI_DIR]/tools/cooja/apps/collect-view [CONTIKI_DIR]/tools/cooja/apps/powertracker Example Demonstrating the Trickle Library's Functionality diff --git a/examples/mqtt-client/Makefile b/examples/mqtt-client/Makefile new file mode 100644 index 000000000..c4741bec9 --- /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 + +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 8b4e3b043..44bba8877 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:`, where `` gets +client-id `d:contiki-ng:mqtt-client:`, where `` gets constructed from the device's IEEE address. Subscribing diff --git a/arch/platform/openmote-cc2538/dev/button-sensor.h b/examples/mqtt-client/arch/cpu/cc2538/builtin-sensors.c similarity index 65% rename from arch/platform/openmote-cc2538/dev/button-sensor.h rename to examples/mqtt-client/arch/cpu/cc2538/builtin-sensors.c index 9a08634ae..f22c33835 100644 --- a/arch/platform/openmote-cc2538/dev/button-sensor.h +++ b/examples/mqtt-client/arch/cpu/cc2538/builtin-sensors.c @@ -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 - * - * The user button will generate a sensors_changed event on press as - * well as on release. - * - * @{ - * - * \file - * Header for the OpenMote-CC2538 button driver - */ -/*---------------------------------------------------------------------------*/ -#ifndef BUTTON_SENSOR_H_ -#define BUTTON_SENSOR_H_ -/*---------------------------------------------------------------------------*/ -#include "lib/sensors.h" -/*---------------------------------------------------------------------------*/ -#define BUTTON_SENSOR "Button" +#include "contiki.h" +#include "dev/cc2538-sensors.h" +#include "mqtt-client.h" -extern const struct sensors_sensor button_sensor; +#include +#include /*---------------------------------------------------------------------------*/ -extern process_event_t button_press_duration_exceeded; +#define TMP_BUF_SZ 32 /*---------------------------------------------------------------------------*/ -#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 +char tmp_buf[TMP_BUF_SZ]; /*---------------------------------------------------------------------------*/ -#endif /* BUTTON_SENSOR_H_ */ +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 000000000..50a765b52 --- /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/arch/platform/srf06-cc26xx/srf06/button-sensor.h b/examples/mqtt-client/arch/cpu/cc26xx-cc13xx/builtin-sensors.c similarity index 66% rename from arch/platform/srf06-cc26xx/srf06/button-sensor.h rename to examples/mqtt-client/arch/cpu/cc26xx-cc13xx/builtin-sensors.c index 1c810c96d..3b346fc1b 100644 --- a/arch/platform/srf06-cc26xx/srf06/button-sensor.h +++ b/examples/mqtt-client/arch/cpu/cc26xx-cc13xx/builtin-sensors.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 @@ -28,33 +29,54 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** - * \addtogroup srf06-common-peripherals - * @{ - * - * \file - * Header file for the SmartRF06EB + CC13xx/CC26xxEM Button Driver - */ -/*---------------------------------------------------------------------------*/ -#ifndef BUTTON_SENSOR_H_ -#define BUTTON_SENSOR_H_ -/*---------------------------------------------------------------------------*/ -#include "lib/sensors.h" -/*---------------------------------------------------------------------------*/ -#define BUTTON_SENSOR "Button" -/*---------------------------------------------------------------------------*/ -#define BUTTON_SENSOR_VALUE_STATE 0 -#define BUTTON_SENSOR_VALUE_DURATION 1 +#include "contiki.h" +#include "batmon-sensor.h" +#include "mqtt-client.h" -#define BUTTON_SENSOR_VALUE_RELEASED 0 -#define BUTTON_SENSOR_VALUE_PRESSED 1 +#include +#include /*---------------------------------------------------------------------------*/ -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; +#define TMP_BUF_SZ 32 /*---------------------------------------------------------------------------*/ -#endif /* BUTTON_SENSOR_H_ */ +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 000000000..38af3f62a --- /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 000000000..fcdd0583a --- /dev/null +++ b/examples/mqtt-client/arch/platform/cc2538dk/Makefile.cc2538dk @@ -0,0 +1 @@ +MODULES_REL += arch/cpu/cc2538 diff --git a/arch/platform/srf06-cc26xx/launchpad/button-sensor.h b/examples/mqtt-client/arch/platform/cc2538dk/als-extend.c similarity index 71% rename from arch/platform/srf06-cc26xx/launchpad/button-sensor.h rename to examples/mqtt-client/arch/platform/cc2538dk/als-extend.c index 0c945d3f7..7f9845a42 100644 --- a/arch/platform/srf06-cc26xx/launchpad/button-sensor.h +++ b/examples/mqtt-client/arch/platform/cc2538dk/als-extend.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,33 @@ * 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 - */ -/*---------------------------------------------------------------------------*/ -#ifndef BUTTON_SENSOR_H_ -#define BUTTON_SENSOR_H_ -/*---------------------------------------------------------------------------*/ -#include "lib/sensors.h" -/*---------------------------------------------------------------------------*/ -#define BUTTON_SENSOR "Button" -/*---------------------------------------------------------------------------*/ -#define BUTTON_SENSOR_VALUE_STATE 0 -#define BUTTON_SENSOR_VALUE_DURATION 1 +#include "contiki.h" +#include "als-extend.h" +#include "dev/als-sensor.h" -#define BUTTON_SENSOR_VALUE_RELEASED 0 -#define BUTTON_SENSOR_VALUE_PRESSED 1 +#include +#include /*---------------------------------------------------------------------------*/ -extern const struct sensors_sensor button_left_sensor; -extern const struct sensors_sensor button_right_sensor; +#define TMP_BUF_SZ 32 /*---------------------------------------------------------------------------*/ -#endif /* BUTTON_SENSOR_H_ */ +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/arch/platform/srf06-cc26xx/launchpad/launchpad-sensors.c b/examples/mqtt-client/arch/platform/cc2538dk/als-extend.h similarity index 83% rename from arch/platform/srf06-cc26xx/launchpad/launchpad-sensors.c rename to examples/mqtt-client/arch/platform/cc2538dk/als-extend.h index c940ec68c..f9b8dc9b0 100644 --- a/arch/platform/srf06-cc26xx/launchpad/launchpad-sensors.c +++ b/examples/mqtt-client/arch/platform/cc2538dk/als-extend.h @@ -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,20 +29,13 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -/** - * \addtogroup launchpad-peripherals - * @{ - * - * \file - * Generic module controlling LaunchPad sensors - */ +#ifndef ALS_EXTEND_H_ +#define ALS_EXTEND_H_ /*---------------------------------------------------------------------------*/ #include "contiki.h" -#include "launchpad/button-sensor.h" - -#include +#include "mqtt-client.h" /*---------------------------------------------------------------------------*/ -/** \brief Exports a global symbol to be used by the sensor API */ -SENSORS(&button_left_sensor, &button_right_sensor); +extern const mqtt_client_extension_t als_extend; +/*---------------------------------------------------------------------------*/ +#endif /* ALS_EXTEND_H_ */ /*---------------------------------------------------------------------------*/ -/** @} */ 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 000000000..835b95fa6 --- /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 +/*---------------------------------------------------------------------------*/ +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 000000000..fcdd0583a --- /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/mqtt-client-extensions.c b/examples/mqtt-client/arch/platform/openmote-cc2538/mqtt-client-extensions.c new file mode 100644 index 000000000..022c28e84 --- /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 +/*---------------------------------------------------------------------------*/ +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 000000000..dcec87bad --- /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/mqtt-client-extensions.c b/examples/mqtt-client/arch/platform/srf06-cc26xx/mqtt-client-extensions.c new file mode 100644 index 000000000..559a4ee9b --- /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 +/*---------------------------------------------------------------------------*/ +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 000000000..fcdd0583a --- /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/mqtt-client-extensions.c b/examples/mqtt-client/arch/platform/zoul/mqtt-client-extensions.c new file mode 100644 index 000000000..022c28e84 --- /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 +/*---------------------------------------------------------------------------*/ +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 81% rename from examples/platform-specific/cc2538-common/mqtt-demo/mqtt-demo.c rename to examples/mqtt-client/mqtt-client.c index 18b806ac9..867ef9982 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 +#include +/*---------------------------------------------------------------------------*/ +#define LOG_MODULE "mqtt-client" +#define LOG_LEVEL LOG_LEVEL_NONE /*---------------------------------------------------------------------------*/ /* * IBM server: messaging.quickstart.internetofthings.ibmcloud.com @@ -67,14 +57,20 @@ * 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 +/*---------------------------------------------------------------------------*/ /* * A timeout used when waiting for something to happen (e.g. to connect or to * disconnect) @@ -130,7 +126,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 +135,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 +161,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 +197,12 @@ static int def_rt_rssi = 0; /*---------------------------------------------------------------------------*/ static mqtt_client_config_t conf; /*---------------------------------------------------------------------------*/ -PROCESS(mqtt_demo_process, "MQTT Demo"); +extern const mqtt_client_extension_t *mqtt_client_extensions[]; +extern const uint8_t mqtt_client_extension_count; /*---------------------------------------------------------------------------*/ -int +PROCESS(mqtt_client_process, "MQTT Client"); +/*---------------------------------------------------------------------------*/ +static int ipaddr_sprintf(char *buf, uint8_t buf_len, const uip_ipaddr_t *addr) { uint16_t a; @@ -243,25 +239,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 +275,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 +293,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 +327,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 +342,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 +360,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 +435,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 +447,7 @@ publish(void) /* Publish MQTT topic in IBM quickstart format */ int len; int remaining = APP_BUFFER_SIZE; + int i; seq_nr_value++; @@ -460,13 +456,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 +478,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; + 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, ",\"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; - } - 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 +544,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 +553,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 +567,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 +611,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 +629,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 +645,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 +654,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 +678,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 +715,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 +725,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 +739,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 000000000..c551c701b --- /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 +/*---------------------------------------------------------------------------*/ +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 a3cc4073b..7b041ae38 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 2337ea60f..6037c8172 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 e88913825..d59708d54 100644 --- a/examples/multicast/multicast.csc +++ b/examples/multicast/multicast.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker Example of a uIPv6 network with multicast support diff --git a/examples/multicast/root.c b/examples/multicast/root.c index b4bf9dcdb..f997e9613 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 e15d0f695..34ad6009d 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/zoul/module-macros.h b/examples/multicast/zoul/module-macros.h new file mode 100644 index 000000000..7029c60ea --- /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 045a175cb..10a113798 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 d654784eb..7bb1f1c87 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 0542bfc97..616845525 100644 --- a/examples/nullnet/nullnet-broadcast.csc +++ b/examples/nullnet/nullnet-broadcast.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker NullNet Broadcast Example diff --git a/examples/nullnet/nullnet-unicast.c b/examples/nullnet/nullnet-unicast.c index 98866f381..5dd9d9fcd 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 d756d9892..5a93836cd 100644 --- a/examples/nullnet/nullnet-unicast.csc +++ b/examples/nullnet/nullnet-unicast.csc @@ -4,10 +4,9 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker - NullNet Broadcast Example + NullNet Unicast Example 123456 1000000 @@ -24,8 +23,8 @@ org.contikios.cooja.contikimote.ContikiMoteType mtype634 Cooja Mote Type #1 - [CONTIKI_DIR]/examples/nullnet/nullnet-broadcast.c - make nullnet-broadcast.cooja TARGET=cooja + [CONTIKI_DIR]/examples/nullnet/nullnet-unicast.c + make nullnet-unicast.cooja TARGET=cooja org.contikios.cooja.interfaces.Position org.contikios.cooja.interfaces.Battery org.contikios.cooja.contikimote.interfaces.ContikiVib @@ -176,4 +175,3 @@ 408 - diff --git a/examples/platform-specific/cc2538-common/Makefile b/examples/platform-specific/cc2538-common/Makefile index 70ef1bc3f..c55c65eaf 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 b621dac95..2191d44f0 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 1295da093..000000000 --- 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 777593c88..000000000 --- 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 488e27db9..01ba6fe62 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 80506b26b..40e484bcc 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 000000000..4ba928ad3 --- /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 000000000..d72ab752d --- /dev/null +++ b/examples/platform-specific/cc26xx/ble-ipv6/README.md @@ -0,0 +1,81 @@ +# 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 000000000..79878cf31 --- /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 + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" + +#include "net/ipv6/uip-icmp6.h" + +#include +#include + +#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/arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.h b/examples/platform-specific/cc26xx/ble-ipv6/project-conf.h similarity index 62% rename from arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.h rename to examples/platform-specific/cc26xx/ble-ipv6/project-conf.h index 1a993d3be..815cfb90a 100644 --- a/arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.h +++ b/examples/platform-specific/cc26xx/ble-ipv6/project-conf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2017, Graz University of Technology * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,45 +27,44 @@ * 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-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 - * - * @{ - * - * \file - * Header file for the CC13xx/CC26xx GPIO interrupt management - */ -/*---------------------------------------------------------------------------*/ -#ifndef GPIO_INTERRUPT_H_ -#define GPIO_INTERRUPT_H_ -/*---------------------------------------------------------------------------*/ -#include -/*---------------------------------------------------------------------------*/ -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 + * \author + * Michael Spoerk */ -void gpio_interrupt_register_handler(uint8_t ioid, gpio_interrupt_handler_t f); - -#endif /* GPIO_INTERRUPT_H_ */ /*---------------------------------------------------------------------------*/ -/** - * @} - * @} - */ +#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 f5045a5bd..8c90905af 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)); + } else if(ev == button_hal_periodic_event) { + button_hal_button_t *button = data; - if((CC26XX_DEMO_SENSOR_1)->value(BUTTON_SENSOR_VALUE_DURATION) > - CLOCK_SECOND) { - printf("Long button press!\n"); - } + 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 88b4b0184..3ddf9671b 100644 --- a/examples/platform-specific/cc26xx/cc26xx-web-demo/Makefile +++ b/examples/platform-specific/cc26xx/cc26xx-web-demo/Makefile @@ -1,12 +1,9 @@ -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 - -PROJECTDIRS += $(REST_RESOURCES_DIR) -PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES) +MODULES_REL += ./resources PROJECT_SOURCEFILES += cetic-6lbr-client.c coap-server.c net-uart.c mqtt-client.c PROJECT_SOURCEFILES += httpd-simple.c 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 e14991d04..306b54640 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 #include #include +#include #include "ti-lib.h" /*---------------------------------------------------------------------------*/ @@ -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 e40cd1864..0761725c7 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 e12f2cd16..d3042bf81 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,13 @@ #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_LITE +#include "net/routing/rpl-lite/rpl.h" +#elif ROUTING_CONF_RPL_CLASSIC +#include "net/routing/rpl-classic/rpl.h" +#endif #include #include 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 8897eb23f..54289f102 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 /*---------------------------------------------------------------------------*/ /* 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/mqtt-client.c b/examples/platform-specific/cc26xx/cc26xx-web-demo/mqtt-client.c index 59ecee1ce..7562fb89a 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 f3dc146c9..ca3bf8c82 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 #include +#include #include #include /*---------------------------------------------------------------------------*/ 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 2dccd1b75..a94a0b7a0 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= 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 a52557ffe..46344d1ef 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 +#include /*---------------------------------------------------------------------------*/ 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, "", 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, "", 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, "", 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 85ce353b5..6c396145c 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 /*---------------------------------------------------------------------------*/ 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 86346a999..81575f345 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 +#include /*---------------------------------------------------------------------------*/ 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, "", 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, "", 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 b5fe9adb9..9ccc79e97 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 2fb424a03..1c708b539 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 /*---------------------------------------------------------------------------*/ 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 fc2d23ab1..8231dd4ea 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 21f6acc1d..46da822d3 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 e56ee93e6..cac8033b7 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 90be80149..23b1c50d7 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 1b13ef3e0..d0437d869 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 1e3ab0842..2fb2d7761 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 #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-dr1175-node/Makefile b/examples/platform-specific/jn516x/rpl/coap-dr1175-node/Makefile index 9a393ff14..3670d12c4 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 2cd40c283..443cf4fbe 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 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-dr1199-node/Makefile b/examples/platform-specific/jn516x/rpl/coap-dr1199-node/Makefile index 32231f636..b2286e272 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 0309538ec..d341170ad 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 #include -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/node/Makefile b/examples/platform-specific/jn516x/rpl/node/Makefile index 37f6c7c79..b5a14023a 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 3c24f36c1..71e015e6d 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/tools/rpl-tools.c b/examples/platform-specific/jn516x/rpl/tools/rpl-tools.c deleted file mode 100644 index 570be8566..000000000 --- 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 - */ - -#include "contiki.h" -#include "contiki-net.h" -#include "net/ipv6/uip.h" -#include "rpl.h" -#include "rpl-dag-root.h" -#include -#include - -#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 df37a89af..2880a76de 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 0b1bc3414..12350a5f4 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 @@ -37,14 +37,10 @@ #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/routing/routing.h" #include "net/mac/tsch/tsch-schedule.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 +169,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 +207,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/tools/rpl-tools.c b/examples/platform-specific/jn516x/tsch/tools/rpl-tools.c deleted file mode 100644 index e71a19bc9..000000000 --- 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 - */ - -#include "contiki.h" -#include "contiki-net.h" -#include "net/ipv6/uip.h" -#include "rpl.h" -#include "rpl-dag-root.h" -#include -#include - -#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 977210702..d19228f4d 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 115649535..995dc3304 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 -#include +#include "coap-engine.h" +#include +#include #include -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/rpl-border-router/Makefile b/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/Makefile index c88fa5a2b..27454bda2 100644 --- 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 @@ -1,5 +1,7 @@ CONTIKI_PROJECT=rpl-border-router +PLATFORMS_ONLY = jn516x + TARGET ?= jn516x JN516x_WITH_DONGLE = 1 @@ -7,8 +9,7 @@ CONTIKI=../../../../../.. PROJECT_SOURCEFILES += slip-bridge.c slip.c -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/rpl-border-router/rpl-border-router.c b/examples/platform-specific/jn516x/tsch/tx-power-verification/rpl-border-router/rpl-border-router.c index e15a77989..642e370d1 100644 --- 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 @@ -36,14 +36,13 @@ #include "contiki-net.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-ds6.h" -#include "rpl.h" +#include "net/routing/routing.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 "coap-engine.h" #include #include @@ -56,10 +55,10 @@ 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 void get_rssi_handler(coap_message_t *request, coap_message_t *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void get_last_rssi_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__); } @@ -67,45 +66,45 @@ static int content_len = 0; PROCESS(border_router_process, "Border router process"); AUTOSTART_PROCESSES(&border_router_process); -RESOURCE(resource_get_rssi, +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) +get_rssi_handler(coap_message_t *request, coap_message_t *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) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == 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); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } -RESOURCE(resource_get_last_rssi, +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) +get_last_rssi_handler(coap_message_t *request, coap_message_t *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) { + coap_get_header_accept(request, &accept); + if(accept == -1 || accept == 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); + coap_set_header_content_format(response, TEXT_PLAIN); + coap_set_payload(response, (uint8_t *)content, content_len); } } @@ -157,11 +156,12 @@ PROCESS_THREAD(border_router_process, ev, data) uip_debug_ipaddr_print(&prefix); PRINTF("\n"); - rpl_tools_init(&prefix); + NETSTACK_ROUTING.root_set_prefix(&prefix, NULL); + NETSTACK_ROUTING.root_start(); - rest_init_engine(); - rest_activate_resource(&resource_get_rssi, "Get-RSSI"); - rest_activate_resource(&resource_get_last_rssi, "Get-Last-RSSI"); + coap_engine_init(); + coap_activate_resource(&resource_get_rssi, "Get-RSSI"); + coap_activate_resource(&resource_get_last_rssi, "Get-Last-RSSI"); PROCESS_END(); diff --git a/examples/platform-specific/jn516x/tsch/uart1-test-node/Makefile b/examples/platform-specific/jn516x/tsch/uart1-test-node/Makefile index ca520969d..22c5ee216 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/uart1-test-node.c b/examples/platform-specific/jn516x/tsch/uart1-test-node/uart1-test-node.c index 244672d48..dd647fa21 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 -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 d5d2de18d..393a385c3 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 6d9639da0..000000000 --- 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=) -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 000000000..b7a5ff778 --- /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=) +$(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 1ef59b369..4effcc876 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 000000000..0202f0e92 --- /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 000000000..3853b313a --- /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 9df517886..6b4025cd3 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 #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 f990fcf38..695eca6a2 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 #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 bf1b35fff..dc3e23e67 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 80339a4ad..6fa071617 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 +#include /*---------------------------------------------------------------------------*/ /* * 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 de851dcf1..da515a62e 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 bc018f171..88dcb3ce2 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 8715c949f..df8ef9da8 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 012010c87..b7a1acddc 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 #include #include diff --git a/examples/platform-specific/zoul/orion/README.md b/examples/platform-specific/zoul/orion/README.md index bd57b5284..d32cc4bcb 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 de6df0e34..22354dc98 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 18f1a5e91..ebbd34fb0 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 /*---------------------------------------------------------------------------*/ 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 ec1288753..da2387a85 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 /*---------------------------------------------------------------------------*/ 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 ca2361f0a..0bc244395 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 8300617ca..4d532912a 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 75430a6e4..420fc52cc 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 433f58426..5f2a98e24 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(" (%u.%02u sec)", numticks / CLOCK_SECOND, + ADD(" (%u.%02u sec)", 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 61d9cf432..43d381c3f 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 75430a6e4..cb458a6d9 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 0bb364aba..942a01933 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 9aca10bbc..9a3bc0aec 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 978aa69f8..74ff66e03 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 6a17df99c..9b30ab25a 100644 --- a/examples/platform-specific/zoul/test-lcd.c +++ b/examples/platform-specific/zoul/test-lcd.c @@ -47,7 +47,7 @@ #include #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 ed6f72327..0e6fce588 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 76c07cb8b..4d2db2a85 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 30b6d6150..416d18093 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 61be96086..000000000 --- a/examples/rpl-border-router/common/webserver.c +++ /dev/null @@ -1,334 +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 -#include - -/*---------------------------------------------------------------------------*/ -static const char *TOP = "Contiki-NG\n"; -static const char *BOTTOM = "\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
");
-
-  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("
Routes
\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("ipaddr);
-    ADD("]/status.shtml>");
-    ipaddr_add(&r->ipaddr);
-    ADD("");
-#else
-    ipaddr_add(&r->ipaddr);
-#endif
-#else
-#if WEBSERVER_CONF_ROUTE_LINKS
-    ADD("ipaddr);
-    ADD("]/status.shtml>");
-    SEND_STRING(&s->sout, buf);
-    blen = 0;
-    ipaddr_add(&r->ipaddr);
-    ADD("");
-#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("
"); - -#if RPL_WITH_NON_STORING - ADD("Links
\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("");
-      ipaddr_add(&child_ipaddr);
-      ADD("");
-#else
-      ipaddr_add(&child_ipaddr);
-#endif
-#else
-#if WEBSERVER_CONF_ROUTE_LINKS
-      ADD("");
-      SEND_STRING(&s->sout, buf);
-      blen = 0;
-      ipaddr_add(&child_ipaddr);
-      ADD("");
-#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("
"); -#endif /* RPL_WITH_NON_STORING */ - -#if WEBSERVER_CONF_FILESTATS - static uint16_t numtimes; - ADD("
This page sent %u times", ++numtimes); -#endif - -#if WEBSERVER_CONF_LOADTIME - numticks = clock_time() - numticks + 1; - ADD(" (%u.%02u sec)", numticks / CLOCK_SECOND, (100 * (numticks % CLOCK_SECOND)) / CLOCK_SECOND)); -#endif - - SEND_STRING(&s->sout, buf); - 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-border-router/embedded/Makefile b/examples/rpl-border-router/embedded/Makefile deleted file mode 100644 index 5faba70c8..000000000 --- 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 c3d097481..000000000 --- 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/native/Makefile b/examples/rpl-border-router/native/Makefile deleted file mode 100644 index 30690df0f..000000000 --- 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/tools/rpl-tools.h b/examples/rpl-border-router/project-conf.h similarity index 80% rename from examples/platform-specific/jn516x/tsch/tools/rpl-tools.h rename to examples/rpl-border-router/project-conf.h index b04cdb712..a2ffcc950 100644 --- a/examples/platform-specific/jn516x/tsch/tools/rpl-tools.h +++ b/examples/rpl-border-router/project-conf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Swedish Institute of Computer Science. + * Copyright (c) 2010, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,10 +27,20 @@ * SUCH DAMAGE. * */ -/** - * \author Simon Duquennoy - */ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ -void rpl_tools_init(uip_ipaddr_t *br_prefix); -void print_network_status(void); +#ifndef WEBSERVER_CONF_CFS_CONNS +#define WEBSERVER_CONF_CFS_CONNS 2 +#endif + +#ifndef BORDER_ROUTER_CONF_WEBSERVER +#define BORDER_ROUTER_CONF_WEBSERVER 1 +#endif + +#if BORDER_ROUTER_CONF_WEBSERVER +#define UIP_CONF_TCP 1 +#endif + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/rpl-border-router/embedded/sky/target-conf.h b/examples/rpl-border-router/sky/module-macros.h similarity index 89% rename from examples/rpl-border-router/embedded/sky/target-conf.h rename to examples/rpl-border-router/sky/module-macros.h index 70cdab319..f9c7b408c 100644 --- a/examples/rpl-border-router/embedded/sky/target-conf.h +++ b/examples/rpl-border-router/sky/module-macros.h @@ -29,13 +29,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /*---------------------------------------------------------------------------*/ -#ifndef TARGET_CONF_H_ -#define TARGET_CONF_H_ -/*---------------------------------------------------------------------------*/ /* Save some RAM and ROM */ #define QUEUEBUF_CONF_NUM 4 #define UIP_CONF_BUFFER_SIZE 140 #define BORDER_ROUTER_CONF_WEBSERVER 0 /*---------------------------------------------------------------------------*/ -#endif /* TARGET_CONF_H_ */ -/*---------------------------------------------------------------------------*/ diff --git a/examples/rpl-border-router/common/httpd-simple.c b/examples/rpl-border-router/webserver/httpd-simple.c similarity index 100% rename from examples/rpl-border-router/common/httpd-simple.c rename to examples/rpl-border-router/webserver/httpd-simple.c 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 000000000..3658381bf --- /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 +#include + +/*---------------------------------------------------------------------------*/ +static const char *TOP = "\n \n Contiki-NG\n \n\n"; +static const char *BOTTOM = "\n\n\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
    \n"); + SEND(&s->sout); + for(nbr = nbr_table_head(ds6_neighbors); + nbr != NULL; + nbr = nbr_table_next(ds6_neighbors, nbr)) { + ADD("
  • "); + ipaddr_add(&nbr->ipaddr); + ADD("
  • \n"); + SEND(&s->sout); + } + ADD("
\n"); + SEND(&s->sout); + +#if (UIP_MAX_ROUTES != 0) + { + static uip_ds6_route_t *r; + ADD(" Routes\n
    \n"); + SEND(&s->sout); + for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { + ADD("
  • "); + ipaddr_add(&r->ipaddr); + ADD("/%u (via ", r->length); + ipaddr_add(uip_ds6_route_nexthop(r)); + ADD(") %lus", (unsigned long)r->state.lifetime); + ADD("
  • \n"); + SEND(&s->sout); + } + ADD("
\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
    \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("
  • "); + ipaddr_add(&child_ipaddr); + + ADD(" (parent: "); + ipaddr_add(&parent_ipaddr); + ADD(") %us", (unsigned int)link->lifetime); + + ADD("
  • \n"); + SEND(&s->sout); + } + } + ADD("
"); + 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 e779b1680..26190e839 100644 --- a/examples/rpl-udp/Makefile +++ b/examples/rpl-udp/Makefile @@ -1,4 +1,5 @@ -all: udp-client udp-server +CONTIKI_PROJECT = udp-client udp-server +all: $(CONTIKI_PROJECT) .PHONY: renode renode: all diff --git a/examples/rpl-udp/cc2538-node.resc b/examples/rpl-udp/cc2538-node.resc index 55a043852..8d5b94329 100644 --- a/examples/rpl-udp/cc2538-node.resc +++ b/examples/rpl-udp/cc2538-node.resc @@ -24,7 +24,7 @@ macro reset sysbus LoadBinary @http://antmicro.com/projects/renode/cc2538_rom_dump.bin-s_524288-0c196cdc21b5397f82e0ff42b206d1cc4b6d7522 0x0 sysbus LoadELF $bin - cpu VectorTableOffset 0x200000 + 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 b37169090..a17dd6f45 100644 --- a/examples/rpl-udp/rpl-udp-cooja.csc +++ b/examples/rpl-udp/rpl-udp-cooja.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker RPL-UDP Example diff --git a/examples/rpl-udp/rpl-udp-sky.csc b/examples/rpl-udp/rpl-udp-sky.csc index f2a217a7b..7975acf05 100644 --- a/examples/rpl-udp/rpl-udp-sky.csc +++ b/examples/rpl-udp/rpl-udp-sky.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker RPL-UDP Example diff --git a/examples/rpl-udp/udp-client.c b/examples/rpl-udp/udp-client.c index 10e336dac..a10d188ac 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" @@ -45,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(); @@ -56,25 +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"); - /* 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), &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 222556d59..399cabfc4 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 2bb2549b1..e207590bb 100644 --- a/examples/sensniff/Makefile +++ b/examples/sensniff/Makefile @@ -1,14 +1,12 @@ CONTIKI_PROJECT = sensniff CONTIKI = ../.. +PLATFORMS_ONLY = cc2538dk openmote-cc2538 zoul srf06-cc26xx jn516x + PROJECT_SOURCEFILES += sensniff-mac.c netstack.c -PROJECTDIRS += pool $(TARGET) +MODULES_REL += pool $(TARGET) --include $(CONTIKI)/Makefile.identify-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/slip-radio/Makefile b/examples/slip-radio/Makefile index d59b5e240..877b109f1 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 +# slip-radio is only intended for platforms with SLIP support +PLATFORMS_EXCLUDE = native nrf52dk + CONTIKI=../.. --include $(CONTIKI)/Makefile.identify-target +include $(CONTIKI)/Makefile.identify-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) - -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 2f05bec5e..4283d0249 100644 --- a/examples/slip-radio/project-conf.h +++ b/examples/slip-radio/project-conf.h @@ -29,11 +29,7 @@ #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 diff --git a/examples/slip-radio/sky/Makefile.sky b/examples/slip-radio/sky/Makefile.sky deleted file mode 100644 index 83a91472d..000000000 --- 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 000000000..1fabdf1cf --- /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 f49e3c4e9..000000000 --- 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 - -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 9cf238741..000000000 --- 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 - -/*---------------------------------------------------------------------------*/ -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 e1efbf4cf..edf219106 100644 --- a/examples/slip-radio/slip-net.c +++ b/examples/slip-radio/slip-net.c @@ -64,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) { diff --git a/examples/slip-radio/slip-radio.c b/examples/slip-radio/slip-radio.c index 53a0324bc..30a9387df 100644 --- a/examples/slip-radio/slip-radio.c +++ b/examples/slip-radio/slip-radio.c @@ -166,6 +166,25 @@ 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] == '?') { @@ -180,6 +199,25 @@ 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; @@ -189,7 +227,9 @@ 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); + if(!cmd_input(uip_buf, uip_len)) { + cmd_send((uint8_t *)"EUnknown command", 16); + } uip_clear_buf(); } /*---------------------------------------------------------------------------*/ diff --git a/examples/storage/antelope-shell/Makefile b/examples/storage/antelope-shell/Makefile index c6ffd276b..3b3f7fd23 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= cc2538 + +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 4d27d6f8f..10d6256fa 100644 --- a/examples/storage/cfs-coffee/Makefile +++ b/examples/storage/cfs-coffee/Makefile @@ -1,7 +1,11 @@ CONTIKI = ../../.. -MODULES += os/services/unit-test +PLATFORMS_ONLY= cc2538 sky -all: test-cfs test-coffee example-coffee +MODULES += os/services/unit-test +MODULES += os/storage/cfs + +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 991e9583b..028f518f8 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/os/contiki-default-conf.h b/os/contiki-default-conf.h index 0395f6ca4..8ec1a41f7 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 62638c8a7..234b759ee 100644 --- a/os/contiki-main.c +++ b/os/contiki-main.c @@ -47,6 +47,7 @@ #include "sys/stack-check.h" #include "dev/watchdog.h" +#include "services/rpl-border-router/rpl-border-router.h" #include "services/orchestra/orchestra.h" #include "services/shell/serial-shell.h" @@ -110,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 9b467363f..1eb50dd8d 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 000000000..ce5f5e8b1 --- /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 + */ +/*---------------------------------------------------------------------------*/ + +#ifndef BLE_HAL_H_ +#define BLE_HAL_H_ + +#include + +/*---------------------------------------------------------------------------*/ +/* 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 000000000..58cded790 --- /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 +#include +#include +/*---------------------------------------------------------------------------*/ +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 000000000..c1822ff8e --- /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 +#include +#include +/*---------------------------------------------------------------------------*/ +/** + * \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 000000000..70b50b688 --- /dev/null +++ b/os/dev/gpio-hal.c @@ -0,0 +1,97 @@ +/* + * 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 +#include +/*---------------------------------------------------------------------------*/ +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) { + 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 000000000..aacbfb1f1 --- /dev/null +++ b/os/dev/gpio-hal.h @@ -0,0 +1,495 @@ +/* + * 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 +/*---------------------------------------------------------------------------*/ +/** + * \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; +/*---------------------------------------------------------------------------*/ +/** + * \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 f7028f0c2..eff3197a1 100644 --- a/os/dev/leds.c +++ b/os/dev/leds.c @@ -1,38 +1,51 @@ /* * 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 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" +#include +#include +/*---------------------------------------------------------------------------*/ +#if LEDS_LEGACY_API /*---------------------------------------------------------------------------*/ void leds_init(void) @@ -59,26 +72,154 @@ leds_get(void) { } /*---------------------------------------------------------------------------*/ void -leds_set(unsigned char ledv) +leds_set(leds_mask_t ledv) { leds_arch_set(ledv); } /*---------------------------------------------------------------------------*/ void -leds_on(unsigned char ledv) +leds_on(leds_mask_t ledv) { leds_arch_set(leds_arch_get() | ledv); } /*---------------------------------------------------------------------------*/ void -leds_off(unsigned char ledv) +leds_off(leds_mask_t ledv) { leds_arch_set(leds_arch_get() & ~ledv); } /*---------------------------------------------------------------------------*/ void -leds_toggle(unsigned char ledv) +leds_toggle(leds_mask_t ledv) { leds_arch_set(leds_arch_get() ^ ledv); } /*---------------------------------------------------------------------------*/ +#else /* LEDS_LEGACY_API */ +/*---------------------------------------------------------------------------*/ +extern const leds_t leds_arch_leds[]; +/*---------------------------------------------------------------------------*/ +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 d99fb8196..654ed250e 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 LEDs API defines a set of functions for accessing LEDs for - * Contiki plaforms with LEDs. + * The LED HAL provides a set of functions that can manipulate LEDS. * - * A platform with LED support must implement this API. + * 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 assumption is that each LED is connected to a GPIO pin using either + * positive or negative logic. + * + * 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" +#include +#include +/*---------------------------------------------------------------------------*/ +#if LEDS_CONF_LEGACY_API +/** + * \brief Define to 1 to enabled the legacy LED API. + */ +#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 + +#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 +#define LEDS_ALL 7 +#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); /** - * Blink 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. */ -void leds_blink(void); - -#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_ALL -#define LEDS_ALL LEDS_CONF_ALL -#else /* LEDS_CONF_ALL */ -#define LEDS_ALL 7 -#endif /* LEDS_CONF_ALL */ +void leds_single_on(leds_num_t led); /** - * Returns the current status of all leds + * \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. */ -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_off(leds_num_t led); /** - * Leds implementation + * \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_arch_init(void); -unsigned char leds_arch_get(void); -void leds_arch_set(unsigned char 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/lib/heapmem.c b/os/lib/heapmem.c index 54394ff01..7a90f1357 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 401da617e..afa9df585 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 +/*---------------------------------------------------------------------------*/ 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/net/app-layer/coap/Makefile.coap b/os/net/app-layer/coap/Makefile.coap new file mode 100644 index 000000000..4afecf78a --- /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 6ecdce7c6..e08a321d1 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 */ -#include +/** + * \addtogroup coap + * @{ + */ + #include +#include #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-block1" +#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 a6b1de5ab..50638ef66 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 */ +/** + * \addtogroup coap + * @{ + */ + #ifndef COAP_BLOCK1_H_ #define COAP_BLOCK1_H_ +#include "coap.h" #include #include -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 000000000..0d2c5dc58 --- /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 + */ + +/** + * \addtogroup coap + * @{ + */ + +#include "coap-engine.h" +#include "coap-blocking-api.h" +#include "sys/cc.h" +#include +#include +#include +#include + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-blocking-api" +#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/examples/rpl-border-router/embedded/project-conf.h b/os/net/app-layer/coap/coap-blocking-api.h similarity index 53% rename from examples/rpl-border-router/embedded/project-conf.h rename to os/net/app-layer/coap/coap-blocking-api.h index 30ef25b90..d9a916c04 100644 --- a/examples/rpl-border-router/embedded/project-conf.h +++ b/os/net/app-layer/coap/coap-blocking-api.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,30 +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. */ -#ifndef PROJECT_ROUTER_CONF_H_ -#define PROJECT_ROUTER_CONF_H_ +/** + * \addtogroup coap + * @{ + */ + +#ifndef COAP_BLOCKING_API_H_ +#define COAP_BLOCKING_API_H_ + +#include "sys/pt.h" +#include "coap-transactions.h" + /*---------------------------------------------------------------------------*/ -/* Include target-specific header */ -#ifdef TARGET_CONF_PATH -#include TARGET_CONF_PATH -#endif /* TARGET_CONF_PATH */ +/*- Client Part -------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -#ifndef UIP_FALLBACK_INTERFACE -#define UIP_FALLBACK_INTERFACE rpl_interface -#endif +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; -#ifndef WEBSERVER_CONF_CFS_CONNS -#define WEBSERVER_CONF_CFS_CONNS 2 -#endif +typedef void (* coap_blocking_response_handler_t)(coap_message_t *response); -#ifndef BORDER_ROUTER_CONF_WEBSERVER -#define BORDER_ROUTER_CONF_WEBSERVER 1 -#endif +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)); -#if BORDER_ROUTER_CONF_WEBSERVER -#define UIP_CONF_TCP 1 -#endif +#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 /* PROJECT_ROUTER_CONF_H_ */ +#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 000000000..652856233 --- /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 +#include + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "coap-callback-api" +#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/examples/rpl-border-router/embedded/sky/slip-bridge-putchar.c b/os/net/app-layer/coap/coap-callback-api.h similarity index 62% rename from examples/rpl-border-router/embedded/sky/slip-bridge-putchar.c rename to os/net/app-layer/coap/coap-callback-api.h index f7f501ba1..6de7ab587 100644 --- a/examples/rpl-border-router/embedded/sky/slip-bridge-putchar.c +++ b/os/net/app-layer/coap/coap-callback-api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 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,39 +26,48 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * */ -/*---------------------------------------------------------------------------*/ -#include "contiki.h" -#include "dev/slip.h" -#include -/*---------------------------------------------------------------------------*/ -#define SLIP_END 0300 -#undef putchar -/*---------------------------------------------------------------------------*/ -int -putchar(int c) -{ - static char debug_frame = 0; +/** + * \file + * Callback API for doing CoAP requests + * Adapted from the blocking API + * \author + * Joakim Eriksson, joakime@sics.se + */ - if(!debug_frame) { /* Start of debug output */ - slip_arch_writeb(SLIP_END); - slip_arch_writeb('\r'); /* Type debug line == '\r' */ - debug_frame = 1; - } +/** + * \addtogroup coap + * @{ + */ - /* Need to also print '\n' because for example COOJA will not show - any output before line end */ - slip_arch_writeb((char)c); +#ifndef COAP_CALLBACK_API_H_ +#define COAP_CALLBACK_API_H_ + +#include "coap-engine.h" +#include "coap-transactions.h" +#include "sys/cc.h" - /* - * 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; -} /*---------------------------------------------------------------------------*/ +/*- 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 2aabc4be4..911017ed8 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 */ -#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 cfa73abcf..f73a5b950 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 */ -#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 000000000..969791241 --- /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 + * Joakim Eriksson + */ + +/** + * \addtogroup coap-transport + * @{ + */ + +#ifndef COAP_ENDPOINT_H_ +#define COAP_ENDPOINT_H_ + +#include "contiki.h" +#include + +#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 8cde3b836..1327cb3e6 100644 --- a/os/net/app-layer/coap/coap-engine.c +++ b/os/net/app-layer/coap/coap-engine.c @@ -31,490 +31,484 @@ /** * \file - * CoAP implementation for the REST Engine. + * CoAP implementation Engine. * \author * Matthias Kovatsch */ +/** + * \addtogroup coap + * @{ + */ + +#include "coap-engine.h" #include "sys/cc.h" +#include "lib/list.h" #include #include +#include #include -#include "coap-engine.h" -#define DEBUG 0 -#if DEBUG -#include -#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-engine" +#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); +LIST(coap_resource_periodic_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) { - erbium_status_code = NO_ERROR; + 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) +{ + 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. */ - PRINTF("handle_incoming_data(): received uip_datalen=%u \n", - (uint16_t)uip_datalen()); - - /* 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; - } - - /* 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 */ - } 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; - } - } - } 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 { - - 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); + /* Check response code before doing observe! */ + if(request->code == COAP_GET) { + coap_observe_handler(NULL, request, response); } - 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; - - coap_clear_transaction(transaction); - - /* check if someone registered for the response */ - if(callback) { - callback(callback_data, message); - } - } - /* 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); - } -#endif /* COAP_OBSERVE_CLIENT */ - } /* request or response */ - } /* parsed correctly */ - - /* if(parsed correctly) */ - if(erbium_status_code == NO_ERROR) { - if(transaction) { - coap_send_transaction(transaction); + return status; } - } 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)); } } + 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; + } - /* if(new data) */ - return erbium_status_code; -} -/*---------------------------------------------------------------------------*/ -void -coap_init_engine(void) -{ - process_start(&coap_engine, NULL); -} -/*---------------------------------------------------------------------------*/ -void -coap_set_service_callback(service_callback_t callback) -{ - 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_set_status_code(response, NOT_FOUND_4_04); + + return COAP_HANDLER_STATUS_CONTINUE; } + /*---------------------------------------------------------------------------*/ /*- 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 +extern coap_resource_t res_well_known_core; /*---------------------------------------------------------------------------*/ -PROCESS_THREAD(coap_engine, ev, data) +/*- Internal API ------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +int +coap_receive(const coap_endpoint_t *src, + uint8_t *payload, uint16_t payload_length) { - PROCESS_BEGIN(); - PRINTF("Starting %s receiver...\n", coap_rest_implementation.name); + /* static declaration reduces stack peaks and program code size */ + 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; - rest_activate_resource(&res_well_known_core, ".well-known/core"); + coap_status_code = coap_parse_message(message, payload, payload_length); + coap_set_src_endpoint(message, src); - coap_register_as_transaction_handler(); - coap_init_connection(SERVER_LISTEN_PORT); + if(coap_status_code == NO_ERROR) { - while(1) { - PROCESS_YIELD(); + /*TODO duplicates suppression, if required by application */ - if(ev == tcpip_event) { - coap_receive(); - } else if(ev == PROCESS_EVENT_TIMER) { - /* retransmissions are handled here */ - coap_check_transactions(); + 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; + } + + /* 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); */ + + /* 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 { + 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 */ + } 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 { + coap_status_code = SERVICE_UNAVAILABLE_5_03; + coap_error_message = "NoFreeTraBuffer"; + } /* if(transaction buffer) */ + + /* handle responses */ + } else { + + 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); + } + + 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; + + coap_clear_transaction(transaction); + + /* check if someone registered for the response */ + if(callback) { + callback(callback_data, message); + } + } + /* if(ACKed transaction) */ + transaction = NULL; + +#if COAP_OBSERVE_CLIENT + /* 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 */ + + /* if(parsed correctly) */ + if(coap_status_code == NO_ERROR) { + if(transaction) { + coap_send_transaction(transaction); } - } /* while (1) */ + } 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; - PROCESS_END(); + 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 coap_status_code; } /*---------------------------------------------------------------------------*/ -/*- Client Part -------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ void -coap_blocking_request_callback(void *callback_data, void *response) +coap_engine_init(void) { - struct request_state_t *state = (struct request_state_t *)callback_data; - - state->response = (coap_packet_t *)response; - process_poll(state->process); -} -/*---------------------------------------------------------------------------*/ -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)) -{ - 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); - } else { - PRINTF("WRONG BLOCK %lu/%lu\n", res_block, state->block_num); - ++block_error; - } - } else { - PRINTF("Could not allocate transaction buffer"); - PT_EXIT(&state->pt); - } - } while(more && block_error < COAP_MAX_ATTEMPTS); - - PT_END(&state->pt); -} -/*---------------------------------------------------------------------------*/ -/*- 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 + /* 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); + list_init(coap_resource_periodic_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_activate_resource(coap_resource_t *resource, const char *path) +{ + 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); + list_add(coap_resource_periodic_services, resource->periodic); + 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); + } +} +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/*- Internal API ------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +coap_resource_t * +coap_get_first_resource(void) +{ + return list_head(coap_resource_services); +} +/*---------------------------------------------------------------------------*/ +coap_resource_t * +coap_get_next_resource(coap_resource_t *resource) +{ + return list_item_next(resource); +} +/*---------------------------------------------------------------------------*/ +static int +invoke_coap_resource_service(coap_message_t *request, coap_message_t *response, + uint8_t *buffer, uint16_t buffer_size, + int32_t *offset) +{ + 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 { + allowed = 0; + coap_set_status_code(response, METHOD_NOT_ALLOWED_4_05); + } + break; + } + } + 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; +} +/*---------------------------------------------------------------------------*/ +/* 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 8b3ae1d2c..140ed0211 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 */ -#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-timer.h" + +typedef enum { + COAP_HANDLER_STATUS_CONTINUE, + COAP_HANDLER_STATUS_PROCESSED +} coap_handler_status_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); + +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); +/*---------------------------------------------------------------------------*/ +/* 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; + }; +}; + +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" -#define SERVER_LISTEN_PORT UIP_HTONS(COAP_SERVER_PORT) - -typedef coap_packet_t rest_request_t; -typedef coap_packet_t rest_response_t; - -void coap_init_engine(void); - -/*---------------------------------------------------------------------------*/ -/*- Client Part -------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -struct request_state_t { - struct pt pt; - struct process *process; - coap_transaction_t *transaction; - coap_packet_t *response; - uint32_t block_num; -}; - -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) \ - ); \ - } -/*---------------------------------------------------------------------------*/ - -#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 2f26a69f6..1eb8737e9 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 @@ -29,61 +29,69 @@ */ /** - * \addtogroup oma-lwm2m - * @{ - * + * \file + * A simple keystore with fixed credentials. + * \author + * Niclas Finne + * Joakim Eriksson */ /** - * \file - * Implementation of the Contiki OMA LWM2M TLV writer - * \author - * Joakim Eriksson - * Niclas Finne + * \addtogroup coap-keystore + * @{ */ -#include "lwm2m-object.h" -#include "oma-tlv.h" +#include "coap-endpoint.h" +#include "coap-keystore.h" +#include + +#ifdef WITH_DTLS +#ifdef COAP_DTLS_PSK_DEFAULT_IDENTITY +#ifdef COAP_DTLS_PSK_DEFAULT_KEY /*---------------------------------------------------------------------------*/ -static size_t -write_boolean_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, - int 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 != 0 ? 1 : 0, - 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 size_t -write_int_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, - int32_t value) -{ - return oma_tlv_write_int32(ctx->resource_id, value, outbuf, outlen); -} -/*---------------------------------------------------------------------------*/ -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); -} -/*---------------------------------------------------------------------------*/ -static size_t -write_string_tlv(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, - const char *value, size_t stringlen) -{ - 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); -} -/*---------------------------------------------------------------------------*/ -const lwm2m_writer_t oma_tlv_writer = { - write_int_tlv, - write_string_tlv, - write_float32fix_tlv, - write_boolean_tlv +static const coap_keystore_t simple_key_store = { + .coap_get_psk_info = get_default_psk_info }; /*---------------------------------------------------------------------------*/ +#endif /* COAP_DTLS_PSK_DEFAULT_KEY */ +#endif /* COAP_DTLS_PSK_DEFAULT_IDENTITY */ +#endif /* WITH_DTLS */ +/*---------------------------------------------------------------------------*/ +void +coap_keystore_simple_init(void) +{ +#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 */ +} +/*---------------------------------------------------------------------------*/ /** @} */ 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 000000000..2252002d4 --- /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 + * Joakim Eriksson + */ + +/** + * \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 000000000..6a3763d5a --- /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 + * Joakim Eriksson + */ + +/** + * \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 000000000..36f3bc016 --- /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 + * Joakim Eriksson + */ + +/** + * \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 000000000..2e6a0a359 --- /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 + * Joakim Eriksson + */ + +/** + * \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 84edec98e..af1e89f14 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 */ -#include -#include +/** + * \addtogroup coap + * @{ + */ #include "coap.h" #include "coap-observe-client.h" +#include "sys/cc.h" +#include "lib/memb.h" +#include "lib/list.h" +#include +#include /* 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-observe-client" +#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 c0ea0c5a2..79625caff 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 */ +/** + * \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 2237e4e25..ac336fbd8 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 */ +/** + * \addtogroup coap + * @{ + */ + #include #include #include "coap-observe.h" +#include "coap-engine.h" +#include "lib/memb.h" +#include "lib/list.h" -#define DEBUG 0 -#if DEBUG -#include -#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-observe" +#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,21 @@ 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); + /* 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, + NULL) > 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, NULL); + } 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 +282,8 @@ 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); + transaction->message_len = + coap_serialize_message(notification, transaction->message); coap_send_transaction(transaction); } @@ -264,16 +292,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 +333,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 7ff2bb502..c276522c5 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 */ +/** + * \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 117e362ab..2893925c9 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 */ -#include -#include "coap-engine.h" +/** + * \addtogroup coap + * @{ + */ -#define DEBUG 0 -#if DEBUG +#include "coap-engine.h" +#include #include -#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-res-well-known-core" +#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 03f95c411..318a4e53d 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 */ -#include "sys/cc.h" -#include -#include +/** + * \addtogroup coap + * @{ + */ + +#include "coap.h" #include "coap-separate.h" #include "coap-transactions.h" +#include "sys/cc.h" +#include -#define DEBUG 0 -#if DEBUG -#include -#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-separate" +#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 1a89ed434..97cbdbf92 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 */ +/** + * \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 000000000..ad1b30d28 --- /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 + * Joakim Eriksson + */ + +/** + * \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-default" +#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 000000000..06a65c7f6 --- /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 + * Joakim Eriksson + */ + +/** + * \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 000000000..0461232ba --- /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 + * Joakim Eriksson + */ + +/** + * \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 + +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 613557f4d..652737b94 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 */ -#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 -#define DEBUG 0 -#if DEBUG -#include -#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-transactions" +#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 49e35c0f2..65334b4eb 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 */ +/** + * \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/tools/collect-view/src/org/contikios/contiki/collect/Link.java b/os/net/app-layer/coap/coap-transport.h similarity index 51% rename from tools/collect-view/src/org/contikios/contiki/collect/Link.java rename to os/net/app-layer/coap/coap-transport.h index 6575801b4..3de6f71dc 100644 --- a/tools/collect-view/src/org/contikios/contiki/collect/Link.java +++ b/os/net/app-layer/coap/coap-transport.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Swedish Institute of Computer Science. + * Copyright (c) 2016-2018, SICS, Swedish ICT AB. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,62 +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. - * - * - * ----------------------------------------------------------------- - * - * 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; - /** - * + * \file + * API for CoAP transport + * \author + * Niclas Finne + * Joakim Eriksson */ -public class Link { - public final Node node; +/** + * \addtogroup coap + * @{ + * + * \defgroup coap-transport CoAP transport API + * @{ + * + * The CoAP transport API defines a common interface for sending/receiving + * CoAP messages. + */ - private double etx; - private int quality = 100; - private long lastActive = 0L; +#ifndef COAP_TRANSPORT_H_ +#define COAP_TRANSPORT_H_ - public Link(Node node) { - this.node = node; - this.lastActive = System.currentTimeMillis(); - } +#include "coap-endpoint.h" - public Node getNode() { - return node; - } +/** + * \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); - public int getQuality() { - return quality; - } +/** + * \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); - public void setQuality(int quality) { - this.quality = quality; - } +/** + * \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); - 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; - } - -} +#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 000000000..ed881ca8b --- /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 + * Joakim Eriksson + */ + +/** + * \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 Length: %u\n", uip_ntohs(UIP_UDP_BUF->srcport), + 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 Length: %u\n", uip_ntohs(UIP_UDP_BUF->srcport), + 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 bcec49cee..42a2d5cef 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 + * + * Joakim Eriksson, joakim.eriksson@ri.se + * Niclas Finne, niclas.finne@ri.se */ +/** + * \addtogroup coap + * @{ + */ + + #include -#include -#include "contiki.h" +#include #include "sys/cc.h" -#include "contiki-net.h" #include "coap.h" #include "coap-transactions.h" -#define DEBUG 0 -#if DEBUG -#include -#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); + 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("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] - ); + 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]); - 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); - - PRINTF("-sent UDP datagram (%u)-\n", length); - - /* 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,72 +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; } - 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; @@ -605,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; @@ -614,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, @@ -668,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, @@ -680,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"; @@ -703,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); @@ -734,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; @@ -745,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 */ @@ -1086,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; } @@ -1104,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 */ @@ -1133,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; } @@ -1151,57 +1074,47 @@ 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) { *payload = coap_pkt->payload; return coap_pkt->payload_len; @@ -1211,13 +1124,12 @@ coap_get_payload(void *packet, const uint8_t **payload) } } 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 616f67d5c..8d9aed61c 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 */ -#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 /* 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_LLH_LEN - UIP_IPH_LEN - UIP_UDPH_LEN) -#error "UIP_CONF_BUFFER_SIZE too small for REST_MAX_CHUNK_SIZE" -#endif +/** + * \brief The max size of the CoAP messages + */ +#define COAP_MAX_PACKET_SIZE (COAP_MAX_HEADER_SIZE + COAP_MAX_CHUNK_SIZE) -/* use Erbium CoAP for the REST Engine. Must come before include of rest-engine.h. */ -#define REST coap_rest_implementation -#include "rest-engine.h" - -/* 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 addc0970b..000000000 --- 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 - */ - -#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 cec590012..000000000 --- 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 - */ - -#include -#include -#include "contiki.h" -#include "rest-engine.h" - -#define DEBUG 0 -#if DEBUG -#include -#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 cf9faa734..000000000 --- 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 - */ - -#ifndef REST_ENGINE_H_ -#define REST_ENGINE_H_ - -#include -#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 000000000..ac8a5aff4 --- /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 000000000..9265583e5 --- /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 + * Joakim Eriksson + */ + +#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 + +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 000000000..ad960b718 --- /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 + * Joakim Eriksson + */ + +#include "dtls-support.h" +#include "lib/random.h" +#include +#include + +/* Log configuration */ +#define LOG_MODULE "dtls-support" +#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 5b683e10b..adac80c3e 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 adbea25e0..00619c354 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 extern uint16_t uip_slen; diff --git a/os/net/ipv6/multicast/smrf.c b/os/net/ipv6/multicast/smrf.c index 00043d60b..86a053648 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 #define DEBUG DEBUG_NONE diff --git a/os/net/ipv6/resolv.h b/os/net/ipv6/resolv.h index ed24d5bce..ac414425f 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 060699e93..3bc7a935e 100644 --- a/os/net/ipv6/sicslowpan.c +++ b/os/net/ipv6/sicslowpan.c @@ -74,12 +74,7 @@ #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" @@ -358,7 +353,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 */ @@ -426,12 +421,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 */ @@ -676,16 +671,15 @@ compress_hdr_iphc(linkaddr_t *link_destaddr) 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 */ hc06_ptr = PACKETBUF_IPHC_BUF + 2; /* @@ -1001,16 +995,15 @@ 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; } @@ -1066,7 +1059,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; @@ -1081,7 +1074,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; @@ -1436,10 +1429,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); @@ -1911,19 +1902,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 e096ce44b..41d317d17 100644 --- a/os/net/ipv6/tcpip.c +++ b/os/net/ipv6/tcpip.c @@ -38,21 +38,15 @@ * \author Julien Abeille (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 @@ -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) @@ -489,23 +478,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 @@ -533,7 +505,7 @@ get_nexthop(uip_ipaddr_t *addr) 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"); @@ -571,9 +543,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); @@ -678,14 +652,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; @@ -855,10 +828,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 bf8c9b0b1..8f84cedb3 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 f83f0ee5b..000000000 --- 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 - * Niclas Finne - * Joakim Eriksson - */ - -#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 267a36aca..6ebbf0aaa 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 +#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 d07f85d78..e49125548 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 ebb7de2d8..9aec47b4a 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 9321b632c..a8fdd88fb 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 acc417670..9f435824c 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 18e9d33e9..6dd178dc8 100644 --- a/os/net/ipv6/uip-ds6.c +++ b/os/net/ipv6/uip-ds6.c @@ -47,6 +47,7 @@ #include #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 736f9bfeb..45394fec3 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 d46a9cd68..be33a1101 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); diff --git a/os/net/ipv6/uip-nd6.c b/os/net/ipv6/uip-nd6.c index 5c01de392..ce555ed53 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 43b989490..2c1e3226b 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 69% rename from os/net/rpl-lite/rpl-ns.c rename to os/net/ipv6/uip-sr.c index 0b31484b8..15b123552 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 */ -#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,75 +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; + 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 != RPL_ROUTE_INFINITE_LIFETIME) { + } 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 5f6e3d86d..7224cea14 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 */ -#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 c3c9f2b38..7751b8fc3 100755 --- a/os/net/ipv6/uip.h +++ b/os/net/ipv6/uip.h @@ -500,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) @@ -620,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) @@ -1238,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 @@ -1260,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: @@ -1295,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 @@ -1367,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 /** @@ -1522,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, @@ -1934,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 72384414a..e913a83e1 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" @@ -161,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]) /** @} */ /** @@ -883,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: @@ -1270,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){ @@ -1363,8 +1349,7 @@ 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 @@ -1392,7 +1377,6 @@ uip_process(uint8_t flag) 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"); diff --git a/os/net/ipv6/uiplib.c b/os/net/ipv6/uiplib.c index 4cc9179eb..693626c87 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 + * Niclas Finne + * Joakim Eriksson + */ #include "net/ipv6/uip.h" #include "net/ipv6/uiplib.h" +#include "net/ipv6/ip64-addr.h" #include +#include -#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,109 @@ 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); + } + } + } + + if(n >= size - 1) { + buf[size - 1] = '\0'; + } + return n; +} +/*---------------------------------------------------------------------------*/ diff --git a/os/net/ipv6/uiplib.h b/os/net/ipv6/uiplib.h index aa23435e0..6a122033e 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/mac/ble/ble-l2cap.c b/os/net/mac/ble/ble-l2cap.c new file mode 100644 index 000000000..f12fbb369 --- /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 + */ +/*---------------------------------------------------------------------------*/ + +#include "net/mac/ble/ble-l2cap.h" + +#include "net/packetbuf.h" +#include "net/netstack.h" +#include "lib/memb.h" +#include "lib/list.h" + +#include + +#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 000000000..73dfa18a5 --- /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 + */ +/*---------------------------------------------------------------------------*/ +#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 0bbc34fb0..74803ecf1 100644 --- a/os/net/mac/csma/csma-output.c +++ b/os/net/mac/csma/csma-output.c @@ -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 */ @@ -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 @@ -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) { diff --git a/os/net/mac/framer/nullframer.c b/os/net/mac/framer/nullframer.c index 3df8f6ea1..019ed2209 100644 --- a/os/net/mac/framer/nullframer.c +++ b/os/net/mac/framer/nullframer.c @@ -36,7 +36,27 @@ * Joakim Eriksson */ #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/sixtop/sixp-nbr.c b/os/net/mac/tsch/sixtop/sixp-nbr.c index 8b5d979de..d736f3668 100644 --- a/os/net/mac/tsch/sixtop/sixp-nbr.c +++ b/os/net/mac/tsch/sixtop/sixp-nbr.c @@ -186,7 +186,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/tsch-log.c b/os/net/mac/tsch/tsch-log.c index 9235d9d7d..fdaaf3b53 100644 --- a/os/net/mac/tsch/tsch-log.c +++ b/os/net/mac/tsch/tsch-log.c @@ -85,10 +85,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 +100,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 +113,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-private.h b/os/net/mac/tsch/tsch-private.h index ec114813e..fc5559b38 100644 --- a/os/net/mac/tsch/tsch-private.h +++ b/os/net/mac/tsch/tsch-private.h @@ -53,10 +53,10 @@ #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 +#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 */ /************ Types ***********/ @@ -94,9 +94,9 @@ 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; +extern unsigned long tx_count; +extern unsigned long rx_count; +extern unsigned long sync_count; /* TSCH processes */ PROCESS_NAME(tsch_process); @@ -124,7 +124,7 @@ void tsch_disassociate(void); #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 +#if CONTIKI_TARGET_COOJA #define BUSYWAIT_UNTIL_ABS(cond, t0, offset) \ while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (offset))) { \ simProcessRunValue = 1; \ @@ -133,6 +133,6 @@ void tsch_disassociate(void); #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 /* CONTIKI_TARGET_COOJA */ #endif /* __TSCH_PRIVATE_H__ */ /** @} */ diff --git a/os/net/mac/tsch/tsch-rpl.c b/os/net/mac/tsch/tsch-rpl.c index ec3f24d8b..fedb4ce58 100644 --- a/os/net/mac/tsch/tsch-rpl.c +++ b/os/net/mac/tsch/tsch-rpl.c @@ -40,21 +40,24 @@ * @{ */ +#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 +69,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 +84,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 +101,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 15be760f5..41fa17e91 100644 --- a/os/net/mac/tsch/tsch-rpl.h +++ b/os/net/mac/tsch/tsch-rpl.h @@ -38,12 +38,13 @@ /********** 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/routing/routing.h" #include "net/mac/tsch/tsch-queue.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 *********/ diff --git a/os/net/mac/tsch/tsch-schedule.c b/os/net/mac/tsch/tsch-schedule.c index dd31afecd..193827f44 100644 --- a/os/net/mac/tsch/tsch-schedule.c +++ b/os/net/mac/tsch/tsch-schedule.c @@ -452,16 +452,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 +468,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-slot-operation.c b/os/net/mac/tsch/tsch-slot-operation.c index 3596b913c..5fcd969d3 100644 --- a/os/net/mac/tsch/tsch-slot-operation.c +++ b/os/net/mac/tsch/tsch-slot-operation.c @@ -59,10 +59,10 @@ #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 +107,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 +208,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 +297,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); ); + } else { + r = rtimer_set(tm, ref_time + offset, 1, (void (*)(struct rtimer *, void *))tsch_slot_operation, NULL); + if(r == RTIMER_OK) { + return 1; + } + } - 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; - } - 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 +316,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 +1011,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.c b/os/net/mac/tsch/tsch.c index 6d60f097a..1dc0bbc7c 100644 --- a/os/net/mac/tsch/tsch.c +++ b/os/net/mac/tsch/tsch.c @@ -60,12 +60,12 @@ #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/mac/mac-sequence.h" +#include "lib/random.h" +#include "net/routing/routing.h" #if TSCH_WITH_SIXTOP #include "net/mac/tsch/sixtop/sixtop.h" @@ -275,7 +275,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) { diff --git a/os/net/nbr-table.c b/os/net/nbr-table.c index f86e5954e..77d3cb07d 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 430a10a8d..d7fad5267 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 4251ef5e9..8528e3fff 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/routing/nullrouting/nullrouting.c b/os/net/routing/nullrouting/nullrouting.c new file mode 100644 index 000000000..14c328b0c --- /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 + */ + +#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 = { + "Null Routing", + 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 000000000..7fe6e7ca8 --- /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 + */ + +#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 96d00f6e1..05adff4de 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 @@ -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 05daec15b..9d2d09b02 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 99% rename from os/net/rpl-classic/rpl-dag.c rename to os/net/routing/rpl-classic/rpl-dag.c index aeed6194e..899322264 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" @@ -1004,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; diff --git a/os/net/rpl-classic/rpl-ext-header.c b/os/net/routing/rpl-classic/rpl-ext-header.c similarity index 96% rename from os/net/rpl-classic/rpl-ext-header.c rename to os/net/routing/rpl-classic/rpl-ext-header.c index 083d26741..e6498b993 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)); @@ -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) diff --git a/os/net/rpl-classic/rpl-icmp6.c b/os/net/routing/rpl-classic/rpl-icmp6.c similarity index 98% rename from os/net/rpl-classic/rpl-icmp6.c rename to os/net/routing/rpl-classic/rpl-icmp6.c index c5114fd14..914575dbf 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; } diff --git a/os/net/rpl-classic/rpl-mrhof.c b/os/net/routing/rpl-classic/rpl-mrhof.c similarity index 99% rename from os/net/rpl-classic/rpl-mrhof.c rename to os/net/routing/rpl-classic/rpl-mrhof.c index 21db377e7..4f5189384 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" 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 1804fd4b7..077977a10 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 aa18823cb..1a679d23b 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 99% rename from os/net/rpl-classic/rpl-private.h rename to os/net/routing/rpl-classic/rpl-private.h index 723154cdd..1259fffeb 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" /*---------------------------------------------------------------------------*/ diff --git a/os/net/rpl-classic/rpl-timers.c b/os/net/routing/rpl-classic/rpl-timers.c similarity index 99% rename from os/net/rpl-classic/rpl-timers.c rename to os/net/routing/rpl-classic/rpl-timers.c index 7742a5fcc..c812a8897 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(); 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 dfa7c99cf..b1905d611 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 2fe9f1dbf..db87cc824 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" @@ -266,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); @@ -328,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 410cce988..a3693f8b9 100644 --- a/os/net/rpl-lite/rpl-conf.h +++ b/os/net/routing/rpl-lite/rpl-conf.h @@ -29,7 +29,7 @@ * This file is part of the Contiki operating system. * */ - + /** * \addtogroup rpl-lite * @{ @@ -62,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 @@ -309,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 100% rename from os/net/rpl-lite/rpl-const.h rename to os/net/routing/rpl-lite/rpl-const.h 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 cfe227d4c..0d5cebe92 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 d6260ff21..af0048c4d 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 96% rename from os/net/rpl-lite/rpl-dag.c rename to os/net/routing/rpl-lite/rpl-dag.c index 36373dfb1..7cf99e03b 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 (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,14 +180,14 @@ find_objective_function(rpl_ocp_t ocp) } /*---------------------------------------------------------------------------*/ void -rpl_global_repair(void) +rpl_global_repair(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 */ + 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)"); + } /* Initiate global repair */ RPL_LOLLIPOP_INCREMENT(curr_instance.dag.version); /* New DAG version */ @@ -191,9 +202,9 @@ 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 */ + if(LOG_INFO_ENABLED) { + rpl_neighbor_print_list("Global repair (before)"); + } /* Re-initialize configuration from DIO */ init_dag_from_dio(dio); rpl_local_repair("Global repair"); @@ -209,7 +220,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 +324,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"); + } } } @@ -391,7 +401,7 @@ process_dio_from_current_dag(uip_ipaddr_t *from, rpl_dio_t *dio) 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(); + 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); @@ -579,9 +589,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 +715,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 bc59ac4bb..f9ae66f5f 100644 --- a/os/net/rpl-lite/rpl-dag.h +++ b/os/net/routing/rpl-lite/rpl-dag.h @@ -58,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 * @@ -78,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 96% rename from os/net/rpl-lite/rpl-ext-header.c rename to os/net/routing/rpl-lite/rpl-ext-header.c index 6031d7eef..af67cdaff 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 , * Simon Duquennoy */ - -#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)); @@ -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 */ 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 3e339e6e2..df61bc325 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); - - /** - * 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); +/** +* 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); /** - * Adds/updates RPL extension headers to current uIP packet. +* 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 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 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 65c486be5..1e4a50423 100644 --- a/os/net/rpl-lite/rpl-icmp6.c +++ b/os/net/routing/rpl-lite/rpl-icmp6.c @@ -44,7 +44,7 @@ * George Oikonomou (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 443d28ef6..fc877b948 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 99% rename from os/net/rpl-lite/rpl-mrhof.c rename to os/net/routing/rpl-lite/rpl-mrhof.c index 9f9ba2889..a0b2546eb 100644 --- a/os/net/rpl-lite/rpl-mrhof.c +++ b/os/net/routing/rpl-lite/rpl-mrhof.c @@ -45,7 +45,7 @@ * Simon Duquennoy */ -#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-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 0a8da44d4..3db84f3a8 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 99% rename from os/net/rpl-lite/rpl-neighbor.c rename to os/net/routing/rpl-lite/rpl-neighbor.c index 96c85a886..d6a545e13 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" 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 319ab2414..028d089c7 100644 --- a/os/net/rpl-lite/rpl-neighbor.h +++ b/os/net/routing/rpl-lite/rpl-neighbor.h @@ -47,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 0e94f73f9..c6f820157 100644 --- a/os/net/rpl-lite/rpl-of0.c +++ b/os/net/routing/rpl-lite/rpl-of0.c @@ -41,7 +41,7 @@ * Simon Duquennoy */ -#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 486ccd5b4..f7a50b858 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 */ } @@ -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 c32f3775c..884a55696 100644 --- a/os/net/rpl-lite/rpl-timers.h +++ b/os/net/routing/rpl-lite/rpl-timers.h @@ -47,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 100% rename from os/net/rpl-lite/rpl-types.h rename to os/net/routing/rpl-lite/rpl-types.h 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 76d49d562..acfe94c37 100644 --- a/os/net/rpl-lite/rpl.c +++ b/os/net/routing/rpl-lite/rpl.c @@ -41,7 +41,8 @@ * Simon Duquennoy */ -#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 90% rename from os/net/rpl-lite/rpl.h rename to os/net/routing/rpl-lite/rpl.h index 9557f41c3..7fb4c8718 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 **********/ @@ -127,11 +126,6 @@ int rpl_is_reachable(void); */ int rpl_lollipop_greater_than(int a, int b); -/** - * Initialize RPL main module - */ -void rpl_init(void); - /** @} */ #endif /* RPL_H */ diff --git a/os/net/rpl-classic/rpl-ns.c b/os/net/rpl-classic/rpl-ns.c deleted file mode 100644 index dc2eb23e4..000000000 --- a/os/net/rpl-classic/rpl-ns.c +++ /dev/null @@ -1,229 +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 - */ - -#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 -#include - -/* 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; - rpl_ns_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; - 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--; - } else if(l->lifetime != 0xffffffff) { - /* Decrement lifetime for all nodes with non-infinite lifetime */ - l->lifetime--; - } - } -} - -#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 dcc7e584a..000000000 --- a/os/net/rpl-classic/rpl-ns.h +++ /dev/null @@ -1,76 +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 - */ - - -#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; - rpl_dag_t *dag; - /* 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 000000000..5da931eeb --- /dev/null +++ b/os/net/security/tinydtls @@ -0,0 +1 @@ +Subproject commit 5da931eeb78d1cd4a1e0068a91de9b78bd3f66de diff --git a/os/services/ipso-objects/Makefile.ipso-objects b/os/services/ipso-objects/Makefile.ipso-objects deleted file mode 100644 index 21c56fed0..000000000 --- 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 000000000..3a557de2b --- /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 + +#define DEBUG 0 +#if DEBUG +#include +#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 adda46d1e..7993cbbb3 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 * Niclas Finne @@ -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: %d\n", input_state); + return input_state; +} +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +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 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; + } } - PRINTF("Read button state (polarity=%d, state=%d): %d\n", - polarity, input_state, value); - return ctx->writer->write_boolean(ctx, outbuf, outsize, value); + return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ -static int -reset_counter(lwm2m_context_t *ctx, const uint8_t *arg, size_t len, - uint8_t *outbuf, size_t outlen) -{ - counter = 0; - return 0; -} -/*---------------------------------------------------------------------------*/ -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 000000000..23b53ef06 --- /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 + * Niclas Finne + */ +#include "ipso-control-template.h" +#include "lwm2m-engine.h" +#include "coap-timer.h" +#include +#include + +#define DEBUG 0 +#if DEBUG +#include +#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 000000000..dfbd7076b --- /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 + * Niclas Finne + */ + +#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 38f150f39..2c64da328 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 @@ -56,146 +56,42 @@ #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) +static lwm2m_status_t +set_value(ipso_control_t *control, uint8_t value) { - 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) -{ - 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"); + leds_off(state->led_value); } - 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"; -} +#endif /* PLATFORM_HAS_LEDS */ -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)); + return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ 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; - } - - 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; -} -/*---------------------------------------------------------------------------*/ -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) { int i; @@ -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 02c4b9be2..97733b629 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; - } - } +static lwm2m_status_t set_value(ipso_control_t *control, uint8_t value); + +IPSO_CONTROL(light_control, 3311, 0, set_value); +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +set_value(ipso_control_t *control, uint8_t value) +{ #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); - } + 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); + } #endif /* IPSO_LIGHT_CONTROL */ - } - return len; + return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ -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; - - 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); -} -/*---------------------------------------------------------------------------*/ -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; - - 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(); - } - } - return len; -} -/*---------------------------------------------------------------------------*/ -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 1e8243f94..f8538ee43 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 6b8f5c2a6..92bdfd8de 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 000000000..bf46ed5ae --- /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 + * Niclas Finne + */ +#include "ipso-sensor-template.h" +#include "lwm2m-engine.h" +#include +#include + +#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 000000000..375dbad7c --- /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 + * Niclas Finne + */ + +#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 1851245e2..c27d8b6ba 100644 --- a/os/services/ipso-objects/ipso-temperature.c +++ b/os/services/ipso-objects/ipso-temperature.c @@ -42,118 +42,56 @@ */ #include +#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 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 -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 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; + IPSO_TEMPERATURE.read_value(value) != 0) { + return LWM2M_STATUS_OK; } - - /* 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"); - } - 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 47c4fe5da..000000000 --- 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 a911c7c4a..9e91b37fd 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 -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-device" +#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; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_device_set_time(int32_t time) +{ + time_offset = time - coap_timer_seconds(); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +write_string(lwm2m_context_t *ctx, const char *text) +{ + lwm2m_object_write_string(ctx, text, strlen(text)); + return LWM2M_STATUS_OK; } /*---------------------------------------------------------------------------*/ static int -set_lwtime(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize, - uint8_t *outbuf, size_t outsize) +output_multi_i16(lwm2m_context_t *ctx, const uint16_t *data, int count) { - /* 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); + 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]); } - /* return the number of bytes read */ + len += lwm2m_object_write_exit_ri(ctx); return len; } + /*---------------------------------------------------------------------------*/ -#ifdef PLATFORM_REBOOT -static struct ctimer reboot_timer; -static void -do_the_reboot(void *ptr) -{ - PLATFORM_REBOOT(); -} static int -reboot(lwm2m_context_t *ctx, const uint8_t *arg, size_t argsize, - uint8_t *outbuf, size_t outsize) +lwm2m_dim_callback(lwm2m_object_instance_t *object, uint16_t resource_id) { - PRINTF("Device will reboot!\n"); - ctimer_set(&reboot_timer, CLOCK_SECOND / 2, do_the_reboot, NULL); + 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_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) +static lwm2m_status_t +lwm2m_callback(lwm2m_object_instance_t *object, lwm2m_context_t *ctx) { - PRINTF("Device will do factory default!\n"); - PLATFORM_FACTORY_DEFAULT(); - return 0; + 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; } -#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_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 4587822d5..d7389153c 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 1e313718f..b96674215 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 */ -#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 #include #include -#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-engine" +#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 */ +#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 */ -#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) -#define BS_REMOTE_PORT UIP_HTONS(5685) +#if USE_RD_CLIENT +#include "lwm2m-rd-client.h" +#endif -static const lwm2m_object_t *objects[MAX_OBJECTS]; -static char endpoint[32]; -static char rd_data[128]; /* allocate some data for the RD */ +/* 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) -PROCESS(lwm2m_rd_client, "LWM2M Engine"); +/* invalid instance ID - ffff object ID */ +#define NO_INSTANCE 0xffffffff -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; +/* 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; -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... */ +/* obj-id / ... */ +static uint16_t lwm2m_buf_lock[4]; +static uint64_t lwm2m_buf_lock_timeout = 0; -void lwm2m_device_init(void); -void lwm2m_security_init(void); -void lwm2m_server_init(void); +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); -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) +static lwm2m_object_t * +get_object(uint16_t object_id) { -#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) -{ - 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) { + lwm2m_object_instance_t *instance; + for(instance = list_head(object_list); + instance != NULL; + instance = instance->next) { + if(instance->object_id == object_id) { + return 1; + } + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_instance(uint16_t object_id, uint16_t instance_id, lwm2m_object_t **o) +{ + 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; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +get_instance_by_context(const lwm2m_context_t *context, lwm2m_object_t **o) +{ + 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); +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +call_instance(lwm2m_object_instance_t *instance, lwm2m_context_t *context) +{ + if(context->level < 3) { + return LWM2M_STATUS_OPERATION_NOT_ALLOWED; + } + + if(instance == NULL) { + /* No instance */ + return LWM2M_STATUS_NOT_FOUND; + } + + 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 +double_buffer_flush(lwm2m_buffer_t *ctxbuf, lwm2m_buffer_t *outbuf, int size) +{ + /* 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(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; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static inline const char * +get_method_as_string(coap_resource_flags_t method) +{ + 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 { + return "UNKNOWN"; + } +} +/*--------------------------------------------------------------------------*/ +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 +parse_path(const char *path, int path_len, + uint16_t *oid, uint16_t *iid, uint16_t *rid) +{ + int ret; + int pos; + uint16_t val; + char c = 0; + + /* get object id */ + LOG_DBG("parse PATH: \""); + LOG_DBG_COAP_STRING(path, path_len); + LOG_DBG_("\"\n"); + + 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++; + } + /* 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; +} +/*--------------------------------------------------------------------------*/ +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) +{ + int ret; + if(context == NULL || path == NULL) { return 0; } -#endif /* UIP_CONF_IPV6_RPL */ - return 1; + + ret = parse_path(path, path_len, &context->object_id, + &context->object_instance_id, &context->resource_id); + + if(ret > 0) { + context->level = ret; + } + + return ret; +} + +/*---------------------------------------------------------------------------*/ +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); + + current_opaque_offset = 0; + current_opaque_callback = cb; } /*---------------------------------------------------------------------------*/ -void -lwm2m_engine_use_bootstrap_server(int use) +int +lwm2m_engine_set_rd_data(lwm2m_buffer_t *outbuf, int block) { - use_bootstrap = use != 0; - if(use_bootstrap) { - process_poll(&lwm2m_rd_client); - } -} -/*---------------------------------------------------------------------------*/ -void -lwm2m_engine_use_registration_server(int use) -{ - use_registration = use != 0; - if(use_registration) { - process_poll(&lwm2m_rd_client); - } -} -/*---------------------------------------------------------------------------*/ -void -lwm2m_engine_register_with_server(const uip_ipaddr_t *server, uint16_t port) -{ - uip_ipaddr_copy(&server_ipaddr, server); - if(port != 0) { - server_port = port; - } else { - server_port = REMOTE_PORT; - } - has_registration_server_info = 1; - registered = 0; - if(use_registration) { - process_poll(&lwm2m_rd_client); - } -} -/*---------------------------------------------------------------------------*/ -static int -update_registration_server(void) -{ - if(has_registration_server_info) { - return 1; + /* 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; } -#if UIP_CONF_IPV6_RPL - { - rpl_dag_t *dag; + if(block == 0) { + LOG_DBG("Starting RD generation\n"); + /* start with simple object instances */ + instance = list_head(object_list); + object = NULL; - /* 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; - } - } -#endif /* UIP_CONF_IPV6_RPL */ - - return 0; -} -/*---------------------------------------------------------------------------*/ -void -lwm2m_engine_register_with_bootstrap_server(const uip_ipaddr_t *server, - uint16_t port) -{ - uip_ipaddr_copy(&bs_server_ipaddr, server); - if(port != 0) { - bs_server_port = port; - } else { - bs_server_port = BS_REMOTE_PORT; - } - has_bootstrap_server_info = 1; - bootstrapped = 0; - registered = 0; - if(use_bootstrap) { - process_poll(&lwm2m_rd_client); - } -} -/*---------------------------------------------------------------------------*/ -static int -update_bootstrap_server(void) -{ - if(has_bootstrap_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) { - uip_ipaddr_copy(&bs_server_ipaddr, &dag->dag_id); - bs_server_port = REMOTE_PORT; - return 1; - } - } -#endif /* UIP_CONF_IPV6_RPL */ - - return 0; -} -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(lwm2m_rd_client, ev, data) -{ - static coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */ - static struct etimer et; - - PROCESS_BEGIN(); - - printf("RD Client started with endpoint '%s'\n", endpoint); - - etimer_set(&et, 15 * CLOCK_SECOND); - - while(1) { - PROCESS_YIELD(); - - 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); - - printf("Registering ID with bootstrap server ["); - uip_debug_ipaddr_print(&bs_server_ipaddr); - printf("]:%u as '%s'\n", uip_ntohs(bs_server_port), endpoint); - - 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); - } - } - } - - if(bootstrapped == 1) { - /* Not ready. Lets retry with the bootstrap server again */ - bootstrapped = 0; - } - - } 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; - } - } - } - } - } - - coap_set_payload(request, (uint8_t *)rd_data, pos); - - 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) { + /* No simple object instances available */ + object = list_head(generic_object_list); + if(object == NULL) { + /* No objects of any kind available */ + return 0; } - /* for now only register once... registered = 0; */ - etimer_set(&et, 15 * CLOCK_SECOND); + if(object->impl != NULL) { + instance = object->impl->get_first(NULL); + } + } + + 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... */ + } + + 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) ? "," : "", + instance->object_id, instance->instance_id); + LOG_DBG_((pos > 0 || block > 0) ? "," : "", + 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) ? "," : "", + object->impl->object_id); + LOG_DBG_((pos > 0 || block > 0) ? "," : "", + object->impl->object_id); + } else { + len = 0; + } + lwm2m_buf.len += len; + if(instance != NULL) { + instance = next_object_instance(NULL, object, instance); + } + + 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; + } + + if(object != NULL && object->impl != NULL) { + instance = object->impl->get_first(NULL); + } + + if(instance == NULL && object == NULL && lwm2m_buf.len <= maxsize) { + /* Data generation is done. No more messages are needed after this. */ + break; + } + } + + 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) -{ - lwm2m_security_init(); - lwm2m_server_init(); - lwm2m_device_init(); -} -/*---------------------------------------------------------------------------*/ -static int -parse_next(const char **path, int *path_len, uint16_t *value) -{ - 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; - } - } - return 1; -} -/*---------------------------------------------------------------------------*/ -int -lwm2m_engine_parse_context(const lwm2m_object_t *object, - const char *path, int path_len, - lwm2m_context_t *context) -{ - int ret; - if(context == NULL || object == NULL || path == NULL) { - return 0; - } - 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; - - 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]; - } - } - 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; - } - } - rest_activate_resource(lwm2m_object_get_coap_resource(object), - (char *)object->path); - return found; -} -/*---------------------------------------------------------------------------*/ -static const lwm2m_instance_t * -get_first_instance_of_object(uint16_t id, lwm2m_context_t *context) -{ - const lwm2m_object_t *object; - int i; - - object = lwm2m_engine_get_object(id); - if(object == NULL) { - /* No object with the specified id found */ - 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]; - } - } - return NULL; -} -/*---------------------------------------------------------------------------*/ -static const lwm2m_instance_t * -get_instance(const lwm2m_object_t *object, lwm2m_context_t *context, int depth) -{ - 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]; - } - } - } - return NULL; -} -/*---------------------------------------------------------------------------*/ -static const lwm2m_resource_t * -get_resource(const lwm2m_instance_t *instance, lwm2m_context_t *context) -{ - 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]; - } - } - } - return NULL; -} -/*---------------------------------------------------------------------------*/ -/** - * @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) -{ - const lwm2m_instance_t *instance; - int len, rdlen, i; - - PRINTF("", object->id); - rdlen = snprintf(buffer, size, "", - 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(",", 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; - } - } - return rdlen; -} -/*---------------------------------------------------------------------------*/ -static int -write_rd_link_data(const lwm2m_object_t *object, - const lwm2m_instance_t *instance, - char *buffer, size_t size) -{ - 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; - } - - for(i = 0; i < instance->count; i++) { - resource = &instance->resources[i]; - PRINTF(",<%d/%d/%d>", object->id, instance->id, resource->id); - - len = snprintf(&buffer[rdlen], size - rdlen, - ",<%d/%d/%d>", object->id, instance->id, resource->id); - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; - } - } - return rdlen; -} -/*---------------------------------------------------------------------------*/ -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) -{ - 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; - } - - 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); - } - } 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; - } - } 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"); - } - } - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; - } - if(len > 0) { - s = ","; - } - } - PRINTF("]}\n"); - len = snprintf(&buffer[rdlen], size - rdlen, "]}"); - rdlen += len; - if(len < 0 || rdlen >= size) { - return -1; - } - - return rdlen; -} -/*---------------------------------------------------------------------------*/ -/** - * @brief Set the writer pointer to the proper writer based on the Accept: header +/* + * 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 + * 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 + * 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) { switch(accept) { case LWM2M_TLV: - context->writer = &oma_tlv_writer; + 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: - PRINTF("Unknown Accept type %u, using LWM2M plain text\n", accept); + 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; } /*---------------------------------------------------------------------------*/ -/** - * @brief Set the reader pointer to the proper reader based on the Content-format: header +/* + * 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 + * 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) { switch(content_format) { case LWM2M_TLV: - context->reader = &oma_tlv_reader; + 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: - PRINTF("Unknown content type %u, using LWM2M plain text\n", accept); + LOG_WARN("Unknown content type %u, using LWM2M plain text\n", + content_format); context->reader = &lwm2m_plain_text_reader; break; } } + /*---------------------------------------------------------------------------*/ -void -lwm2m_engine_handler(const lwm2m_object_t *object, - void *request, void *response, - uint8_t *buffer, uint16_t preferred_size, - int32_t *offset) +/* 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 len; - const char *url; - 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 */ + 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; - 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; - } - if(!REST.get_header_accept(request, &accept)) { - PRINTF("No Accept header, using same as Content-format...\n"); - accept = format; + if(instance == NULL) { + /* No existing instance */ + return LWM2M_STATUS_NOT_FOUND; } - 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); + 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; + } - /* 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); + /* copy out the out-buffer as read will use its own - will be same for disoc when + read is fixed */ + outbuf = ctx->outbuf; -#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"; + /* 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 { - method_str = "UNKNOWN"; - } - 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); + /* 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] = ' '; } } -#endif /* (DEBUG) & DEBUG_PRINT */ + lwm2m_buf_lock_timeout = coap_timer_uptime() + 1000; - instance = get_instance(object, &context, depth); + 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); - /* 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; - } else { - 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); + /* 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) ? "":",", + 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); - 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; - } - } + 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; - if(instance == NULL) { - /* could for some reason not create the instance */ - REST.set_response_status(response, NOT_ACCEPTABLE_4_06); - return; - } + lv = ctx->level; - 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"); + /* 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; + } - 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); + 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; } - } 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); + + 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])); } } } - pos = pos + len; - } while(len > 0 && pos < plen); + 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; + } + } + } } - return; + 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; } - 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; - } - /* 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); + /* 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 lwm2m_object_instance_t * +create_instance(lwm2m_context_t *context, lwm2m_object_t *object) +{ + lwm2m_object_instance_t *instance; + if(object == NULL || object->impl == NULL || + object->impl->create_instance == NULL) { + return NULL; + } + + /* 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 instance; +} +/*---------------------------------------------------------------------------*/ +#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) +{ + 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; } - /* 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); - } else { - PRINTF("Execute callback - no exec callback\n"); - REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); - } - } 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); - } - } - } 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); + 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 instance; +} +/*---------------------------------------------------------------------------*/ +static int +check_write(lwm2m_context_t *ctx, lwm2m_object_instance_t *instance, int rid) +{ + int 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; + } + } + } + /* 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; +} +/*---------------------------------------------------------------------------*/ +static lwm2m_status_t +process_tlv_write(lwm2m_context_t *ctx, lwm2m_object_t *object, + int rid, uint8_t *data, int len) +{ + 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 LWM2M_STATUS_ERROR; +} +/*---------------------------------------------------------------------------*/ +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) +{ + /* 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; + + olv = ctx->level; + inbuf = ctx->inbuf->buffer; + inpos = ctx->inbuf->pos; + insize = ctx->inbuf->size; + + 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; + } + + /* Here we have a success! */ + return LWM2M_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +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) +{ + 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(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; + } + + found++; + if(instance->instance_id > max_id) { + max_id = instance->instance_id; + } + if(instance->instance_id < min_id) { + min_id = instance->instance_id; + } + } + } + + 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; + } + } + list_add(object_list, object); +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif + return 1; } /*---------------------------------------------------------------------------*/ void -lwm2m_engine_delete_handler(const lwm2m_object_t *object, void *request, - void *response, uint8_t *buffer, - uint16_t preferred_size, int32_t *offset) +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 1; +} +/*---------------------------------------------------------------------------*/ +void +lwm2m_engine_remove_generic_object(lwm2m_object_t *object) +{ + list_remove(generic_object_list, object); +#if USE_RD_CLIENT + lwm2m_rd_client_set_update_rd(); +#endif +} +/*---------------------------------------------------------------------------*/ +static lwm2m_object_instance_t * +next_object_instance(const lwm2m_context_t *context, lwm2m_object_t *object, + lwm2m_object_instance_t *last) +{ + 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); +} +/*---------------------------------------------------------------------------*/ +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; + int depth; lwm2m_context_t context; + 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; - 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); + /* Initialize the context */ + memset(&context, 0, sizeof(context)); + memset(&outbuf, 0, sizeof(outbuf)); + memset(&inbuf, 0, sizeof(inbuf)); - REST.set_response_status(response, DELETED_2_02); + 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; + } + 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 + + /* Set default reader/writer */ + context.reader = &lwm2m_plain_text_reader; + context.writer = &lwm2m_tlv_writer; + + + 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; + } + + 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; + } + + instance = get_instance_by_context(&context, &object); + + /* + * 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 plen = coap_get_payload(request, &data); + if(plen > 0) { + LOG_DBG("Data: '"); + LOG_DBG_COAP_STRING((const char *)data, plen); + LOG_DBG_("'\n"); + } + } + } + + /* 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; + } + + /* 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; + } + break; + default: + success = LWM2M_STATUS_OPERATION_NOT_ALLOWED; + break; + } + + 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); + } + + 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 { + /* this signals to CoAP that there is no more CoAP messages to expect */ + *offset = -1; + } + } + } else { + LOG_DBG("["); + LOG_DBG_COAP_STRING(url, url_len); + LOG_DBG_("] no data in reply\n"); + } + } 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_notify_object_observers(lwm2m_object_instance_t *obj, + uint16_t resource) +{ + 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 5512a326d..62a667e99 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 000000000..e89c3dab4 --- /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 +#include + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-firmware" +#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 000000000..2b83922cd --- /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 8924ceb8c..8ad8be9c4 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 Eriksson added JSON reader parts */ #include "lwm2m-object.h" @@ -48,43 +49,201 @@ #include #include -#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 -write_boolean(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, +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(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 bc1a1e32a..8267d0246 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 2f5ddb6ed..000000000 --- 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 - * Niclas Finne - */ - -#include "lwm2m-object.h" -#include -/*---------------------------------------------------------------------------*/ -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 a5ff53ac4..c6c582a35 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 * Niclas Finne @@ -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 +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; -/* 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 +typedef enum { + LWM2M_STATUS_OK, -#define LWM2M_OBJECT_STR_HELPER(x) (uint8_t *) #x -#define LWM2M_OBJECT_STR(x) LWM2M_OBJECT_STR_HELPER(x) + /* Internal server error */ + LWM2M_STATUS_ERROR, + /* Error from writer */ + LWM2M_STATUS_WRITE_ERROR, + /* Error from reader */ + LWM2M_STATUS_READ_ERROR, -#define LWM2M_OBJECT_PATH_STR_HELPER(x) #x -#define LWM2M_OBJECT_PATH_STR(x) LWM2M_OBJECT_PATH_STR_HELPER(x) + 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; -struct lwm2m_reader; -struct lwm2m_writer; /* 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; - uint8_t resource_index; - /* TODO - add uint16_t resource_instance_id */ + uint16_t resource_instance_id; - const struct lwm2m_reader *reader; - const struct lwm2m_writer *writer; + uint8_t resource_index; + 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; + + 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; +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); +}; -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; +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 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; +typedef lwm2m_status_t +(* lwm2m_write_opaque_callback)(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx, int num_to_write); -#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); - -static inline int -lwm2m_object_is_resource_callback(const lwm2m_resource_t *resource) -{ - return resource != NULL && resource->type == LWM2M_RESOURCE_TYPE_CALLBACK; -} - -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) -{ - return (resource_t *)object->coap_resource; -} +void lwm2m_engine_set_opaque_callback(lwm2m_context_t *ctx, lwm2m_write_opaque_callback cb); static inline void -lwm2m_object_notify_observers(const lwm2m_object_t *object, char *path) +lwm2m_notify_observers(char *path) { - coap_notify_observers_sub(lwm2m_object_get_coap_resource(object), 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_write_opaque_stream(lwm2m_context_t *ctx, int size, lwm2m_write_opaque_callback cb) +{ + /* 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; +} + +/* Resource instance functions (_ri)*/ + +static inline size_t +lwm2m_object_write_enter_ri(lwm2m_context_t *ctx) +{ + 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 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) +{ + 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 b2bc5dcbe..bbd293aa0 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 #include -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-plain-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 bf12a118c..7922a8ce8 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 000000000..0f904ee4d --- /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 + * Niclas Finne + * Joel Hoglund + */ + +#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 +#include +#include + +#if UIP_CONF_IPV6_RPL +#include "rpl.h" +#endif /* UIP_CONF_IPV6_RPL */ + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-rd-client" +#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 000000000..7fba7e0ae --- /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 + * Niclas Finne + */ + +#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 953279b4d..5fe0c31cb 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 +#include +#include #include "lwm2m-object.h" #include "lwm2m-engine.h" +#include "lwm2m-server.h" +#include "lwm2m-security.h" +#include "coap-keystore.h" +#include "lib/list.h" -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-security" +#define LOG_LEVEL LOG_LEVEL_LWM2M -#ifdef LWM2M_CONF_SERVER_MAX_COUNT -#define MAX_COUNT LWM2M_CONF_SERVER_MAX_COUNT -#else -#define MAX_COUNT 2 -#endif +#define MAX_COUNT LWM2M_SERVER_MAX_COUNT -/* hoping that we do not get more than 64 bytes... */ -#define MAX_SIZE 64 +static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx); -static int32_t bs_arr[MAX_COUNT]; -static int32_t secmode_arr[MAX_COUNT]; -static int32_t sid_arr[MAX_COUNT]; +static lwm2m_object_instance_t *get_by_id(uint16_t instance_id, + lwm2m_status_t *status); -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]; +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 +}; -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); +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; +} + +/*---------------------------------------------------------------------------*/ +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 */ - for(i = 0; i < MAX_COUNT; i++) { - security_instances[i] = template; - security_instances[i].id = i; - } + LOG_INFO("init\n"); - /** - * 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); + list_init(instances_list); + + for(i = 0; i < MAX_COUNT; i++) { + instances[i].instance.instance_id = LWM2M_OBJECT_INSTANCE_NONE; + } + if(lwm2m_engine_add_generic_object(®_object)) { + +#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 000000000..9fb3df78f --- /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 9de678682..67b2c45ba 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 +#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 -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-server" +#define LOG_LEVEL LOG_LEVEL_LWM2M -#ifdef LWM2M_CONF_SERVER_MAX_COUNT -#define MAX_COUNT LWM2M_CONF_SERVER_MAX_COUNT -#else -#define MAX_COUNT 2 -#endif +#define MAX_COUNT LWM2M_SERVER_MAX_COUNT -static int32_t sid_arr[MAX_COUNT]; -static int32_t lifetime_arr[MAX_COUNT]; -static lwm2m_instance_t server_instances[MAX_COUNT]; +static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *object, + lwm2m_context_t *ctx); -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); +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 */ - for(i = 0; i < MAX_COUNT; i++) { - server_instances[i] = template; - server_instances[i].id = i; - } + LOG_INFO("init\n"); - /** - * 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); + list_init(server_list); + + for(i = 0; i < MAX_COUNT; i++) { + server_instances[i].instance.instance_id = LWM2M_OBJECT_INSTANCE_NONE; + } + 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 000000000..733b0889d --- /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 58e1dcc54..cbeed6bd2 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 /*---------------------------------------------------------------------------*/ 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 7e6540c18..15db7024d 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 */ -#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 000000000..6df16447e --- /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 + * Niclas Finne + */ + +#include "lwm2m-object.h" +#include "lwm2m-tlv.h" + +/* Log configuration */ +#include "coap-log.h" +#define LOG_MODULE "lwm2m-tlv-writer" +#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 6ae5edd14..681ccf280 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 */ -#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 c07df31cc..2bda7f8bb 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 #include -#include "oma-tlv.h" +#include "lwm2m-tlv.h" -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif +/* 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(DEBUG) { - int i; - PRINTF("TLV:"); - for(i = 0; i < pos + tlv->length; i++) { - PRINTF("%02x", buffer[i]); - } - PRINTF("\n"); + if(tlv->value != NULL && tlv->length > 0) { + memcpy(&buffer[pos], tlv->value, tlv->length); } - return pos + tlv->length; + if(LOG_DBG_ENABLED) { + int i; + LOG_DBG("TLV: "); + for(i = 0; i < pos + ((tlv->value != NULL) ? tlv->length : 0); i++) { + LOG_DBG_("%02x", buffer[i]); + } + LOG_DBG_("\n"); + } + + 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 1bd5fd94a..2766263fa 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 */ -#ifndef OAM_TLV_H_ -#define OAM_TLV_H_ +#ifndef LWM2M_TLV_H_ +#define LWM2M_TLV_H_ -#include "contiki.h" +#include +#include 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 fbafa4654..723b9e847 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 3ea78ca96..8b9929c03 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/rpl-border-router/Makefile.rpl-border-router b/os/services/rpl-border-router/Makefile.rpl-border-router new file mode 100644 index 000000000..61ba5fa59 --- /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 000000000..c62f7df54 --- /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 d1d8cdafc..6b565a7ff 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 100% rename from examples/rpl-border-router/embedded/slip-bridge.c rename to os/services/rpl-border-router/embedded/slip-bridge.c 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 f14ec1d86..f3fad0b9b 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 - */ - -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 000000000..a225e1666 --- /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 75788a920..9d0e2eb9f 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 +#include "shell.h" +#include #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) { + 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("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) { - /* 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 7b002183e..bcfb829b7 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 fd5e3cde7..3da0ef000 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 -#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: ;;...;*/ -/* 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 841a31f67..6527738ad 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 ba3288777..f07a41fdd 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 25d58aab0..50d66ad05 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 7c14e1ef5..f8ff63660 100644 --- a/os/services/shell/shell-commands.c +++ b/os/services/shell/shell-commands.c @@ -58,14 +58,16 @@ #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 #define PING_TIMEOUT (5 * CLOCK_SECOND) @@ -98,7 +100,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 +148,51 @@ 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: "); + 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); + + } + + 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,56 +396,12 @@ 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_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); - - } - - PT_END(pt); -} -/*---------------------------------------------------------------------------*/ -static PT_THREAD(cmd_rpl_global_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 global repair\n") + NETSTACK_ROUTING.global_repair("Shell"); PT_END(pt); } @@ -406,12 +411,12 @@ PT_THREAD(cmd_rpl_local_repair(struct pt *pt, shell_output_func output, char *ar { PT_BEGIN(pt); - SHELL_OUTPUT(output, "Triggering RPL local repair\n"); - rpl_local_repair("Shell"); + SHELL_OUTPUT(output, "Triggering routing local repair\n"); + NETSTACK_ROUTING.local_repair("Shell"); PT_END(pt); } -#endif /* UIP_CONF_IPV6_RPL_LITE */ +#endif /* UIP_CONF_IPV6_RPL */ /*---------------------------------------------------------------------------*/ static PT_THREAD(cmd_ipaddr(struct pt *pt, shell_output_func output, char *args)) @@ -551,12 +556,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 +574,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 +594,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 +617,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 +627,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 +713,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 +722,14 @@ 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" }, { "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 d89672a13..4f1b4186c 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 a2853efd2..c821fe77c 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 d363ac933..c3282b536 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 b40dc525f..04192642f 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 cad604efb..4bdefecf2 100644 --- a/os/storage/antelope/aql-lexer.c +++ b/os/storage/antelope/aql-lexer.c @@ -42,6 +42,7 @@ #include #include #include +#include struct keyword { char *string; diff --git a/os/storage/antelope/index.c b/os/storage/antelope/index.c index 5c96bf459..7e05d0738 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 @@ -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 de7b28b36..6c9863e8f 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 75cbf730e..53c7eca53 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 3e2452c61..4851f562a 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 a2cd10eb7..dcf91c4ef 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 3aa25b22c..161527d47 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/ctimer.c b/os/sys/ctimer.c index 66698a8e6..1d628677b 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 59f665d10..02ad5df11 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/log-conf.h b/os/sys/log-conf.h index d52765c31..24cf21f71 100644 --- a/os/sys/log-conf.h +++ b/os/sys/log-conf.h @@ -133,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 d4b21639d..90709ec5f 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 b0624bbc7..e27a3007e 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 */ @@ -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/process.h b/os/sys/process.h index bd206b6e7..5cffdb526 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/timer.h b/os/sys/timer.h index b05963e47..54abcb3c2 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/01-compile-base/Makefile b/tests/01-compile-base/Makefile index 78efc6411..0c7e248e0 100644 --- a/tests/01-compile-base/Makefile +++ b/tests/01-compile-base/Makefile @@ -4,6 +4,7 @@ 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 \ @@ -12,10 +13,14 @@ libs/energest/native \ libs/energest/sky \ libs/data-structures/native \ libs/data-structures/sky \ +libs/stack-check/sky \ +ipso-objects/native \ +ipso-objects/native:MAKE_WITH_DTLS=1 \ rpl-udp/sky \ rpl-border-router/native \ rpl-border-router/sky \ slip-radio/sky \ +ipv6-hooks/sky \ nullnet/native \ TOOLS= diff --git a/tests/02-compile-arm-ports-01/Makefile b/tests/02-compile-arm-ports-01/Makefile index b54acc303..51b232173 100644 --- a/tests/02-compile-arm-ports-01/Makefile +++ b/tests/02-compile-arm-ports-01/Makefile @@ -11,10 +11,30 @@ 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 \ @@ -22,15 +42,17 @@ coap/cc2538dk \ slip-radio/cc2538dk \ ipso-objects/cc2538dk \ multicast/cc2538dk \ +dev/gpio-hal/cc2538dk \ +dev/leds/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 \ 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/nrf52dk:coap-server \ -platform-specific/nrf52dk/coap-demo/nrf52dk:coap-client:SERVER_IPV6_ADDR=ffff \ +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 \ diff --git a/tests/03-compile-arm-ports-02/Makefile b/tests/03-compile-arm-ports-02/Makefile index 25345e14c..a69ec44a0 100644 --- a/tests/03-compile-arm-ports-02/Makefile +++ b/tests/03-compile-arm-ports-02/Makefile @@ -4,12 +4,18 @@ TOOLSDIR=../../tools EXAMPLES = \ rpl-border-router/zoul \ 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 \ +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/zoul \ +multicast/zoul \ ipso-objects/zoul \ +ipso-objects/zoul:MAKE_WITH_DTLS=1 \ hello-world/zoul \ sensniff/zoul \ sensniff/zoul:ZOUL_CONF_SUB_GHZ_SNIFFER=1 \ @@ -29,11 +35,31 @@ 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 \ -rpl-border-router/openmote-cc2538 +dev/gpio-hal/openmote-cc2538 \ +dev/leds/openmote-cc2538 \ +rpl-border-router/openmote-cc2538 \ +ipv6-hooks/openmote-cc2538 \ TOOLS= diff --git a/tests/07-simulation-base/02-ringbufindex.csc b/tests/07-simulation-base/02-ringbufindex.csc index 2b3722197..5b236bc5a 100644 --- a/tests/07-simulation-base/02-ringbufindex.csc +++ b/tests/07-simulation-base/02-ringbufindex.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker [APPS_DIR]/radiologger-headless diff --git a/tests/07-simulation-base/03-nullnet-broadcast.csc b/tests/07-simulation-base/03-nullnet-broadcast.csc index 911f998f4..302a04b9b 100644 --- a/tests/07-simulation-base/03-nullnet-broadcast.csc +++ b/tests/07-simulation-base/03-nullnet-broadcast.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker NullNet Broadcast Example diff --git a/tests/07-simulation-base/04-nullnet-broadcast-tsch.csc b/tests/07-simulation-base/04-nullnet-broadcast-tsch.csc index 29c4b6669..498c7fcbe 100644 --- a/tests/07-simulation-base/04-nullnet-broadcast-tsch.csc +++ b/tests/07-simulation-base/04-nullnet-broadcast-tsch.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker NullNet Broadcast Example diff --git a/tests/07-simulation-base/05-nullnet-unicast.csc b/tests/07-simulation-base/05-nullnet-unicast.csc index 628196ac6..12b600317 100644 --- a/tests/07-simulation-base/05-nullnet-unicast.csc +++ b/tests/07-simulation-base/05-nullnet-unicast.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker NullNet Broadcast Example diff --git a/tests/07-simulation-base/06-nullnet-unicast-tsch.csc b/tests/07-simulation-base/06-nullnet-unicast-tsch.csc index 12639e273..e64247095 100644 --- a/tests/07-simulation-base/06-nullnet-unicast-tsch.csc +++ b/tests/07-simulation-base/06-nullnet-unicast-tsch.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker NullNet Broadcast Example diff --git a/tests/07-simulation-base/10-sky-slip-radio.csc b/tests/07-simulation-base/10-sky-slip-radio.csc deleted file mode 100644 index 85eb6e9d5..000000000 --- a/tests/07-simulation-base/10-sky-slip-radio.csc +++ /dev/null @@ -1,189 +0,0 @@ - - - [APPS_DIR]/mrm - [APPS_DIR]/mspsim - [APPS_DIR]/avrora - [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view - [APPS_DIR]/powertracker - - slip radio 1 - 123456 - 1000000 - - se.sics.cooja.radiomediums.UDGM - 15.0 - 15.0 - 1.0 - 1.0 - - - 40000 - - - se.sics.cooja.mspmote.SkyMoteType - sky1 - slip radio - [CONTIKI_DIR]/examples/slip-radio/slip-radio.c - make -j slip-radio.sky TARGET=sky - [CONTIKI_DIR]/examples/slip-radio/slip-radio.sky - se.sics.cooja.interfaces.Position - se.sics.cooja.interfaces.RimeAddress - se.sics.cooja.interfaces.IPAddress - se.sics.cooja.interfaces.Mote2MoteRelations - se.sics.cooja.interfaces.MoteAttributes - se.sics.cooja.mspmote.interfaces.MspClock - se.sics.cooja.mspmote.interfaces.MspMoteID - se.sics.cooja.mspmote.interfaces.SkyButton - se.sics.cooja.mspmote.interfaces.SkyFlash - se.sics.cooja.mspmote.interfaces.SkyCoffeeFilesystem - se.sics.cooja.mspmote.interfaces.Msp802154Radio - se.sics.cooja.mspmote.interfaces.MspSerial - se.sics.cooja.mspmote.interfaces.SkyLED - se.sics.cooja.mspmote.interfaces.MspDebugOutput - se.sics.cooja.mspmote.interfaces.SkyTemperature - - - se.sics.cooja.mspmote.SkyMoteType - sky2 - wait-dag - [CONFIG_DIR]/code-slip-radio/wait-dag.c - make -j wait-dag.sky TARGET=sky - [CONFIG_DIR]/code-slip-radio/wait-dag.sky - se.sics.cooja.interfaces.Position - se.sics.cooja.interfaces.RimeAddress - se.sics.cooja.interfaces.IPAddress - se.sics.cooja.interfaces.Mote2MoteRelations - se.sics.cooja.interfaces.MoteAttributes - se.sics.cooja.mspmote.interfaces.MspClock - se.sics.cooja.mspmote.interfaces.MspMoteID - se.sics.cooja.mspmote.interfaces.SkyButton - se.sics.cooja.mspmote.interfaces.SkyFlash - se.sics.cooja.mspmote.interfaces.SkyCoffeeFilesystem - se.sics.cooja.mspmote.interfaces.Msp802154Radio - se.sics.cooja.mspmote.interfaces.MspSerial - se.sics.cooja.mspmote.interfaces.SkyLED - se.sics.cooja.mspmote.interfaces.MspDebugOutput - se.sics.cooja.mspmote.interfaces.SkyTemperature - - - - - se.sics.cooja.interfaces.Position - 43.565500781711165 - 14.697933087406794 - 0.0 - - - se.sics.cooja.mspmote.interfaces.MspMoteID - 1 - - sky1 - - - - - se.sics.cooja.interfaces.Position - 53.849666651434326 - 14.629826028666905 - 0.0 - - - se.sics.cooja.mspmote.interfaces.MspMoteID - 2 - - sky2 - - - - se.sics.cooja.plugins.SimControl - 315 - 1 - 175 - 433 - 0 - - - se.sics.cooja.plugins.Visualizer - - se.sics.cooja.plugins.skins.IDVisualizerSkin - se.sics.cooja.plugins.skins.GridVisualizerSkin - se.sics.cooja.plugins.skins.TrafficVisualizerSkin - se.sics.cooja.plugins.skins.UDGMVisualizerSkin - 14.682765905648006 0.0 0.0 14.682765905648006 -512.6620495401903 -96.80631081927221 - - 432 - 4 - 291 - 1 - 1 - - - se.sics.cooja.plugins.LogListener - - - - 758 - 3 - 289 - 748 - 159 - - - se.sics.cooja.plugins.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. - true - - 928 - 5 - 159 - 749 - -1 - - - se.sics.cooja.plugins.ScriptRunner - - - true - - 758 - 2 - 502 - 749 - 449 - - - se.sics.cooja.plugins.RadioLogger - - 150 - - 746 - 0 - 657 - 3 - 294 - - diff --git a/tests/07-simulation-base/15-cooja-multicast-11-hops-rollt-tm.csc b/tests/07-simulation-base/15-cooja-multicast-11-hops-rollt-tm.csc index 3b6ad609b..473df16dd 100644 --- a/tests/07-simulation-base/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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker Multicast regression test diff --git a/tests/07-simulation-base/16-cooja-multicast-11-hops-smrf.csc b/tests/07-simulation-base/16-cooja-multicast-11-hops-smrf.csc index f390242ed..e20a30cb6 100644 --- a/tests/07-simulation-base/16-cooja-multicast-11-hops-smrf.csc +++ b/tests/07-simulation-base/16-cooja-multicast-11-hops-smrf.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker Multicast regression test diff --git a/tests/07-simulation-base/17-cooja-multicast-11-hops-esmrf.csc b/tests/07-simulation-base/17-cooja-multicast-11-hops-esmrf.csc index e3f4a3593..14b74b41e 100644 --- a/tests/07-simulation-base/17-cooja-multicast-11-hops-esmrf.csc +++ b/tests/07-simulation-base/17-cooja-multicast-11-hops-esmrf.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker Multicast regression test diff --git a/tests/07-simulation-base/18-cooja-multicast-31-hops.csc b/tests/07-simulation-base/18-cooja-multicast-31-hops.csc index c18de1fce..86ae6916f 100644 --- a/tests/07-simulation-base/18-cooja-multicast-31-hops.csc +++ b/tests/07-simulation-base/18-cooja-multicast-31-hops.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker Multicast regression test diff --git a/tests/07-simulation-base/19-cooja-rpl-tsch.csc b/tests/07-simulation-base/19-cooja-rpl-tsch.csc index 462cf7f84..99e11d63d 100644 --- a/tests/07-simulation-base/19-cooja-rpl-tsch.csc +++ b/tests/07-simulation-base/19-cooja-rpl-tsch.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker RPL+TSCH diff --git a/tests/07-simulation-base/20-cooja-rpl-tsch-orchestra.csc b/tests/07-simulation-base/20-cooja-rpl-tsch-orchestra.csc index fb284128d..5ce2c8121 100644 --- a/tests/07-simulation-base/20-cooja-rpl-tsch-orchestra.csc +++ b/tests/07-simulation-base/20-cooja-rpl-tsch-orchestra.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker RPL+TSCH+Orchestrsa diff --git a/tests/07-simulation-base/21-cooja-rpl-tsch-security.csc b/tests/07-simulation-base/21-cooja-rpl-tsch-security.csc index 2607b8b03..c34e6c4cf 100644 --- a/tests/07-simulation-base/21-cooja-rpl-tsch-security.csc +++ b/tests/07-simulation-base/21-cooja-rpl-tsch-security.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker RPL+TSCH+Security diff --git a/tests/07-simulation-base/31-data-structures-sky.csc b/tests/07-simulation-base/31-data-structures-sky.csc index cd0e35ee3..0e4e81069 100644 --- a/tests/07-simulation-base/31-data-structures-sky.csc +++ b/tests/07-simulation-base/31-data-structures-sky.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker data-structures-sky 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 index e682e43da..dc4d8bb5b 100644 --- a/tests/07-simulation-base/code-data-structures/test-data-structures.c +++ b/tests/07-simulation-base/code-data-structures/test-data-structures.c @@ -30,6 +30,7 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" +#include "lib/list.h" #include "lib/stack.h" #include "lib/queue.h" #include "lib/circular-list.h" @@ -65,6 +66,141 @@ print_test_report(const unit_test_t *utp) } } /*---------------------------------------------------------------------------*/ +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) { @@ -884,6 +1020,7 @@ PROCESS_THREAD(data_structure_test_process, ev, data) 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); diff --git a/tests/07-simulation-base/code-ipv6/sender/unicast-sender.c b/tests/07-simulation-base/code-ipv6/sender/unicast-sender.c index 929e0d584..4e2e664b3 100644 --- a/tests/07-simulation-base/code-ipv6/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 @@ -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-simulation-base/code-slip-radio/wait-dag.c b/tests/07-simulation-base/code-slip-radio/wait-dag.c index 83e3d28f7..a059661b4 100644 --- a/tests/07-simulation-base/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 @@ -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/13-ieee802154/01-panid-handling.csc b/tests/13-ieee802154/01-panid-handling.csc index 0d40497a1..71ec85818 100644 --- a/tests/13-ieee802154/01-panid-handling.csc +++ b/tests/13-ieee802154/01-panid-handling.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker [APPS_DIR]/radiologger-headless diff --git a/tests/13-ieee802154/02-tsch-flush-nbr-queue.csc b/tests/13-ieee802154/02-tsch-flush-nbr-queue.csc index 50b58769f..879b31345 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/13-ieee802154/03-cooja-test-sixtop.csc b/tests/13-ieee802154/03-cooja-test-sixtop.csc index 0826967df..9d5be006c 100644 --- a/tests/13-ieee802154/03-cooja-test-sixtop.csc +++ b/tests/13-ieee802154/03-cooja-test-sixtop.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/13-ieee802154/04-cooja-test-sixp-pkt.csc b/tests/13-ieee802154/04-cooja-test-sixp-pkt.csc index 994a9f8a2..5d5cf7016 100644 --- a/tests/13-ieee802154/04-cooja-test-sixp-pkt.csc +++ b/tests/13-ieee802154/04-cooja-test-sixp-pkt.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/13-ieee802154/05-cooja-test-sixp-trans.csc b/tests/13-ieee802154/05-cooja-test-sixp-trans.csc index e7dfc2373..837fcc321 100644 --- a/tests/13-ieee802154/05-cooja-test-sixp-trans.csc +++ b/tests/13-ieee802154/05-cooja-test-sixp-trans.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/13-ieee802154/06-cooja-test-sixp-nbr.csc b/tests/13-ieee802154/06-cooja-test-sixp-nbr.csc index 00aca5da3..bbffc18a8 100644 --- a/tests/13-ieee802154/06-cooja-test-sixp-nbr.csc +++ b/tests/13-ieee802154/06-cooja-test-sixp-nbr.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/13-ieee802154/07-cooja-test-sixp.csc b/tests/13-ieee802154/07-cooja-test-sixp.csc index 6e6e89ba7..3e884e4b2 100644 --- a/tests/13-ieee802154/07-cooja-test-sixp.csc +++ b/tests/13-ieee802154/07-cooja-test-sixp.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/01-rpl-up-route.csc b/tests/14-rpl-lite/01-rpl-up-route.csc index e35c99f05..899b58bf7 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/03-rpl-28-hours.csc b/tests/14-rpl-lite/03-rpl-28-hours.csc index 56777ba3e..a4c25cc08 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 0bd3c4d63..49e793691 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 2ac006172..6d8283d3e 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/07-rpl-random-rearrangement.csc b/tests/14-rpl-lite/07-rpl-random-rearrangement.csc index dd1e73e9c..6119c6829 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 7e91d4551..bd1114c50 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 8d1540dab..cc1fd3970 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 860b3ab05..f659b4e04 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 d18acd1c2..a3e38edac 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 049de48f5..11a0f3168 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 c877ba8b9..0a0308e22 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/09-rpl-probing.csc b/tests/14-rpl-lite/09-rpl-probing.csc index cf5ab5afb..d79ec7be4 100644 --- a/tests/14-rpl-lite/09-rpl-probing.csc +++ b/tests/14-rpl-lite/09-rpl-probing.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/14-rpl-lite/code/receiver-node.c b/tests/14-rpl-lite/code/receiver-node.c index 352f23cb5..b5265d3f7 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 diff --git a/tests/14-rpl-lite/code/root-node.c b/tests/14-rpl-lite/code/root-node.c index ef3c982ee..7c9fc8c99 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 #include @@ -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 e35c99f05..899b58bf7 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/02-rpl-root-reboot.csc b/tests/15-rpl-classic/02-rpl-root-reboot.csc index d3bc14461..2c89a499e 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/03-rpl-28-hours.csc b/tests/15-rpl-classic/03-rpl-28-hours.csc index 56777ba3e..a4c25cc08 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 000000000..aa412586b --- /dev/null +++ b/tests/15-rpl-classic/05-rpl-up-and-down-routes-non-storing.csc @@ -0,0 +1,341 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype743 + Sender + [CONFIG_DIR]/code/sender-node.c + make clean TARGET=cooja +make -j sender-node.cooja TARGET=cooja DEFINES=RPL_CONF_MOP=RPL_MOP_NON_STORING + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype452 + RPL root + [CONFIG_DIR]/code/root-node.c + make clean TARGET=cooja +make -j root-node.cooja TARGET=cooja DEFINES=RPL_CONF_MOP=RPL_MOP_NON_STORING + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype782 + Receiver + [CONFIG_DIR]/code/receiver-node.c + make clean TARGET=cooja +make -j receiver-node.cooja TARGET=cooja DEFINES=RPL_CONF_MOP=RPL_MOP_NON_STORING + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + -22.5728586847096 + 123.9358664968653 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 116.13379149678028 + 88.36698920455684 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype743 + + + + org.contikios.cooja.interfaces.Position + -1.39303771455413 + 100.21446701029119 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 95.25095618820441 + 63.14998053005015 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 5 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 66.09378990830604 + 38.32698761608261 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 29.05630841762433 + 30.840688165838436 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 7 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 10.931583432822638 + 69.848248459216 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 0.0 + 0.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype452 + + + + org.contikios.cooja.plugins.SimControl + 280 + 1 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + 2.5379695437350276 0.0 0.0 2.5379695437350276 75.2726010197627 15.727272727272757 + + 400 + 2 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + 1184 + 3 + 240 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 962 + 0 + 596 + 603 + 43 + + 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 0bd3c4d63..49e793691 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 e68e5b307..9bbf552d5 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/07-rpl-random-rearrangement.csc b/tests/15-rpl-classic/07-rpl-random-rearrangement.csc index dd1e73e9c..6119c6829 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 7e91d4551..bd1114c50 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 8d1540dab..cc1fd3970 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 860b3ab05..f659b4e04 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 d18acd1c2..a3e38edac 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 049de48f5..11a0f3168 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 c877ba8b9..0a0308e22 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/09-rpl-probing.csc b/tests/15-rpl-classic/09-rpl-probing.csc index cf5ab5afb..d79ec7be4 100644 --- a/tests/15-rpl-classic/09-rpl-probing.csc +++ b/tests/15-rpl-classic/09-rpl-probing.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/15-rpl-classic/10-rpl-multi-dodag.csc b/tests/15-rpl-classic/10-rpl-multi-dodag.csc index ccdaa4734..7d48ae7b4 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 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker [APPS_DIR]/serial2pty [APPS_DIR]/radiologger-headless diff --git a/tests/15-rpl-classic/code/receiver-node.c b/tests/15-rpl-classic/code/receiver-node.c index 770f50f77..20bf165f8 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 @@ -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 ef3c982ee..e25b2872f 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 #include @@ -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/17-tun-rpl-br/01-border-router-cooja.csc b/tests/17-tun-rpl-br/01-border-router-cooja.csc index f2fbdc67f..02808aeec 100644 --- a/tests/17-tun-rpl-br/01-border-router-cooja.csc +++ b/tests/17-tun-rpl-br/01-border-router-cooja.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation 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 index 7c70d4cd8..5b86b690c 100644 --- a/tests/17-tun-rpl-br/02-border-router-cooja-tsch.csc +++ b/tests/17-tun-rpl-br/02-border-router-cooja-tsch.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/17-tun-rpl-br/03-border-router-sky.csc b/tests/17-tun-rpl-br/03-border-router-sky.csc index 62d0ccac0..cec948e0d 100644 --- a/tests/17-tun-rpl-br/03-border-router-sky.csc +++ b/tests/17-tun-rpl-br/03-border-router-sky.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/17-tun-rpl-br/04-border-router-traceroute.csc b/tests/17-tun-rpl-br/04-border-router-traceroute.csc index f2fbdc67f..02808aeec 100644 --- a/tests/17-tun-rpl-br/04-border-router-traceroute.csc +++ b/tests/17-tun-rpl-br/04-border-router-traceroute.csc @@ -4,7 +4,6 @@ [APPS_DIR]/mspsim [APPS_DIR]/avrora [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view [APPS_DIR]/powertracker My simulation diff --git a/tests/17-tun-rpl-br/04-border-router-traceroute.sh b/tests/17-tun-rpl-br/04-border-router-traceroute.sh index 0dba7f835..33e239e08 100755 --- a/tests/17-tun-rpl-br/04-border-router-traceroute.sh +++ b/tests/17-tun-rpl-br/04-border-router-traceroute.sh @@ -17,16 +17,13 @@ java -Xshare:on -jar $CONTIKI/tools/cooja/dist/cooja.jar -nogui=$BASENAME.csc -c JPID=$! sleep 20 -echo "Enabling IPv6" -sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0 - # 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=$! echo "Waiting for network formation" -sleep 5 +sleep 20 # not in real-time, simulates at full speed # Do ping echo "Running Traceroute" diff --git a/tests/17-tun-rpl-br/05-native-ping.sh b/tests/17-tun-rpl-br/05-native-ping.sh index e47536e3f..9e677c16e 100755 --- a/tests/17-tun-rpl-br/05-native-ping.sh +++ b/tests/17-tun-rpl-br/05-native-ping.sh @@ -7,9 +7,6 @@ BASENAME=01-native-ping IPADDR=fd00::302:304:506:708 -echo "Enabling IPv6" -sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0 - # Starting Contiki-NG native node echo "Starting native node" make -C $CONTIKI/examples/hello-world > make.log 2> make.err diff --git a/tests/17-tun-rpl-br/06-native-coap.sh b/tests/17-tun-rpl-br/06-native-coap.sh index a42424ee4..16dd8aab7 100755 --- a/tests/17-tun-rpl-br/06-native-coap.sh +++ b/tests/17-tun-rpl-br/06-native-coap.sh @@ -10,9 +10,6 @@ IPADDR=fd00::302:304:506:708 declare -i OKCOUNT=0 declare -i TESTCOUNT=0 -echo "Enabling IPv6" -sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0 - # Starting Contiki-NG native node echo "Starting native CoAP server" make -C $CONTIKI/examples/coap > make.log 2> make.err @@ -41,10 +38,10 @@ done echo "Closing native node" sleep 2 -pgrep hello-world | sudo xargs kill -9 +pgrep coap-example | sudo xargs kill -9 if [ $TESTCOUNT -eq $OKCOUNT ] ; then - printf "%-40s TEST OK %3d/%d\n" "$BASENAME" "$OKCOUNT" "$TESTCOUNT" > $BASENAME.testlog; + printf "%-32s TEST OK %3d/%d\n" "$BASENAME" "$OKCOUNT" "$TESTCOUNT" > $BASENAME.testlog; else echo "==== make.log ====" ; cat make.log; echo "==== make.err ====" ; cat make.err; 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 000000000..7140d183c --- /dev/null +++ b/tests/17-tun-rpl-br/07-native-border-router-cooja.csc @@ -0,0 +1,254 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/powertracker + + My simulation + 1.0 + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 100.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype295 + Cooja Mote Type #1 + [CONTIKI_DIR]/examples/slip-radio/slip-radio.c + make TARGET=cooja clean +make -j slip-radio.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype686 + Cooja Mote Type #2 + [CONTIKI_DIR]/examples/hello-world/hello-world.c + make TARGET=cooja clean +make -j hello-world.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + 54.36775767371176 + 24.409055040864118 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== + + mtype295 + + + + org.contikios.cooja.interfaces.Position + 83.54989222799365 + 52.63050856506214 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== + + mtype686 + + + + org.contikios.cooja.interfaces.Position + 108.91767775240822 + 78.59778809170032 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== + + mtype686 + + + + org.contikios.cooja.interfaces.Position + 139.91021061864723 + 98.34190023350419 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== + + mtype686 + + + + org.contikios.cooja.plugins.SimControl + 280 + 1 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + true + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.IDVisualizerSkin + 1.9798610460263038 0.0 0.0 1.9798610460263038 -61.112037797038525 -1.2848438586294648 + + 400 + 4 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + ID:4 + + + + 1404 + 2 + 240 + 400 + 160 + + + org.contikios.cooja.plugins.TimeLine + + 0 + 1 + 2 + 3 + + + + 500.0 + + 1804 + 6 + 166 + 0 + 753 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 1124 + 5 + 160 + 680 + 0 + + + org.contikios.cooja.serialsocket.SerialSocketServer + 0 + + 60001 + true + + 362 + 3 + 116 + 13 + 414 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 600 + 0 + 700 + 1037 + 40 + + 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 000000000..d5d2642fe --- /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-nbr.sh $CONTIKI $BASENAME fd00::204:4:4:4 diff --git a/tests/17-tun-rpl-br/test-border-router.sh b/tests/17-tun-rpl-br/test-border-router.sh index 1a1d22a46..ff0e48cce 100755 --- a/tests/17-tun-rpl-br/test-border-router.sh +++ b/tests/17-tun-rpl-br/test-border-router.sh @@ -9,28 +9,29 @@ BASENAME=$2 # Destination IPv6 IPADDR=$3 +# 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 -echo "Enabling IPv6" -sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0 - # 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=$! echo "Waiting for network formation" -sleep 5 +sleep 20 # not in real-time, simulates at full speed # Do ping echo "Pinging" -ping6 $IPADDR -c 5 | tee $BASENAME.scriptlog +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 @@ -40,7 +41,7 @@ sleep 1 rm COOJA.testlog rm COOJA.log -if [ $STATUS -eq 0 ] ; then +if [ $STATUS -eq 0 ] && [ $REPLIES -eq $COUNT ] ; then printf "%-32s TEST OK\n" "$BASENAME" | tee $BASENAME.testlog; else echo "==== $BASENAME.coojalog ====" ; cat $BASENAME.coojalog; diff --git a/tests/17-tun-rpl-br/test-nbr.sh b/tests/17-tun-rpl-br/test-nbr.sh new file mode 100644 index 000000000..9a1824f7c --- /dev/null +++ b/tests/17-tun-rpl-br/test-nbr.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 + +# Simulation file +BASENAME=$2 + +# Destination IPv6 +IPADDR=$3 + +# 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=$! +echo "Waiting for network formation" +sleep 60 # runs in real time so we need to wait a bit + +# 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 000000000..15fd96243 --- /dev/null +++ b/tests/18-coap-lwm2m/06-lwm2m-ipso-test.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 +# Test basename +BASENAME=06-lwm2m-test + +IPADDR=fd00::302:304:506:708 + +# Starting Contiki-NG native node +echo "Starting native node - lwm2m/ipso objects" +make -C $CONTIKI/examples/ipso-objects > make.log 2> make.err +sudo $CONTIKI/examples/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=$! +sleep 50 + +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 000000000..5516eeb46 --- /dev/null +++ b/tests/18-coap-lwm2m/07-lwm2m-standalone-test.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# Contiki directory +CONTIKI=$1 +# Test basename +BASENAME=07-lwm2m-standalone-test + +git clone https://github.com/contiki-ng/example-lwm2m-standalone.git +# Building standalone posix example +make -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=$! + +sleep 50 + +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/Makefile b/tests/18-coap-lwm2m/Makefile new file mode 100644 index 000000000..c46e5271d --- /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 000000000..7ab51eaaa --- /dev/null +++ b/tests/18-coap-lwm2m/example-lwm2m-standalone @@ -0,0 +1 @@ +Subproject commit 7ab51eaaa309c123fbd318c6ad3338cce1e48e48 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 000000000..9c441e4a0 --- /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/compile-all/Makefile b/tests/compile-all/Makefile new file mode 100644 index 000000000..1bd79315c --- /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 000000000..795343eeb --- /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/tools/collect-view/build.xml b/tools/collect-view/build.xml deleted file mode 100644 index 5e7458eb7..000000000 --- a/tools/collect-view/build.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/collect-view/collect-init.script b/tools/collect-view/collect-init.script deleted file mode 100644 index 493cd46c5..000000000 --- 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 634447d2f..000000000 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 f6f7bbf2d..000000000 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 582a4dacd..000000000 --- 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 = ""; - - 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 sensorDataList = new ArrayList(); - private PrintWriter sensorDataOutput; - private boolean isSensorLogUsed; - - private Hashtable nodeTable = new Hashtable(); - private Node[] nodeCache; - - private JFrame window; - private JTabbedPane mainPanel; - private HashMap categoryTable = new HashMap(); - 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(""); - 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(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 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(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 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(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(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 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 dd19761b7..000000000 --- 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/Configurable.java b/tools/collect-view/src/org/contikios/contiki/collect/Configurable.java deleted file mode 100644 index 285bcca91..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/Configurable.java +++ /dev/null @@ -1,50 +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. - * - * - * ----------------------------------------------------------------- - * - * Configurable - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 24 sep 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.util.Properties; - -/** - * - */ -public interface Configurable { - - public void updateConfig(Properties config); - -} 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 2c3c86d5b..000000000 --- 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 comList = new ArrayList(); - private ArrayList moteList = new ArrayList(); - - 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 11809bf46..000000000 --- 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 [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 1878abc41..000000000 --- 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 8dc934bbd..000000000 --- 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 { - - private static final boolean SINGLE_LINK = true; - - private SensorDataAggregator sensorDataAggregator; - private ArrayList sensorDataList = new ArrayList(); - private ArrayList links = new ArrayList(); - - private final String id; - private final String name; - - private Hashtable 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(); - } - 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 8e3445d58..000000000 --- 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 a8bfc2a95..000000000 --- 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 51043d1c3..000000000 --- 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 c2d140a03..000000000 --- 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 5e266c6e1..000000000 --- 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 c624ea64a..000000000 --- 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 337a01a29..000000000 --- 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 ""; - } - - @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 6a04f8b65..000000000 --- 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 "'; - } - - @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 ae1ed52a9..000000000 --- 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 ""; - } - - @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 ea111795a..000000000 --- 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 f898e0e6a..000000000 --- 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 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 selectedMap = new HashMap(); - - 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 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 cb6969331..000000000 --- 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 5a6652b94..000000000 --- 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 nodeTable = new Hashtable(); - private MapNode[] nodeList = new MapNode[0]; - private boolean updateNodeList; - - private MapNode selectedNode; - private ArrayList selectedMapNodes = new ArrayList(); - 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 6b0cffbc8..000000000 --- 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("" + - "

Quick Startup Instructions

" + - "" + - "
  • Connect nodes to USB. Press the Program Nodes... button." + - "
  • Disconnect all except one node. " + - "Press the Connect to Serial button." + - "
  • Press the Start Collect button." + - "
  • Press the Send command to nodes button." + - "" + - ""); - 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 dfda52993..000000000 --- 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_COMPARATOR = new Comparator() { - - 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 sorter = new TableRowSorter(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 ef7b0c7e5..000000000 --- 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 206e25b5c..000000000 --- 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 0 - * 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 - * 0 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 1256b2999..22b1262d9 160000 --- a/tools/cooja +++ b/tools/cooja @@ -1 +1 @@ -Subproject commit 1256b299930b57f4c1d5512f8e96aa22a327591c +Subproject commit 22b1262d9e668d9cf6c8eaf70715f1bcd5728642 diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index 14c1636ae..d8e9c0a79 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -67,24 +67,24 @@ WORKDIR ${HOME} RUN echo "#!/bin/bash\nant -Dbasedir=${COOJA} -f ${COOJA}/build.xml run" > ${HOME}/cooja && \ chmod +x ${HOME}/cooja -# 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 :/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 - -# Enable IPv6 -- must be done at runtime, not in Dockerfile -#RUN sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0 - # 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 :/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 +CMD bash --login diff --git a/tools/doxygen/Doxyfile b/tools/doxygen/Doxyfile index 8073a8239..a7dc79fab 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/sky/uip6-bridge/Makefile b/tools/sky/uip6-bridge/Makefile index ce605851e..55da6798e 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/vagrant/.gitignore b/tools/vagrant/.gitignore new file mode 100644 index 000000000..8000dd9db --- /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 000000000..e64a0314e --- /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 000000000..a4e66ab21 --- /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 000000000..996ffb12e --- /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 f742b66a0..8be720d56 100644 --- a/tools/viewconf.c +++ b/tools/viewconf.c @@ -62,10 +62,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 +150,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 020cbdfec..7221f4033 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 -#define CCIF -#define CLIF /* These names are deprecated, use C99 names. */ typedef uint8_t u8_t;